钱柜游戏官网 > 综合体育 > 任何类都有义务重写这些方法

综合体育

任何类都有义务重写这些方法

Tips
《Effective Java, Third Edition》大器晚成书乌Crane语版已经出版,那本书的第二版恐怕很四个人都读过,可以称作Java四大名著之生龙活虎,然而第二版二〇〇八年出版,到如明儿早上已将近8年的小运,但随着Java 6,7,8,以致9的宣布,Java语言发生了深远的生成。
在这里处第一时间翻译成人中学文版。供大家学习分享之用。

图片 1

10. 重写equals方法时严守通用约定

虽然Object是二个切实的类,但它首假使为延续而陈设的。它的有着非 final方法(equals、hashCode、toString、clone和finalize卡塔尔国都有分明的通用约定( general contracts),因为它们被设计为被子类重写。任何类皆有任务重写那么些艺术,以信守他们的通用约定;假如不这么做,将会阻碍别的注重于约定的类(比方HashMap和HashSet卡塔尔(قطر‎与此类一同平常职业。

本章论述何时以致哪些重写Object类的非final的章程。那生龙活虎章省略了finalize方法,因为它在条目第88中学进行了研商。Comparable.compareTo措施就算不是Object中的方法,因为具备超级多的相仿性,所以也在这里边研讨。

重写equals方法看起来很容易,可是有广大办法会招致重写出错,其结果可能是骇人据书上说的。防止此主题材料的最轻便易行方法不是覆盖equals方法,在此种景观下,类的各类实例只与自个儿相等。假诺知足以下任一下原则,则印证是无可置疑的做法:

  • 各类类的实例都是村生泊长唯生机勃勃的。 对于像Thread这样表示活动实体实际不是值的类来讲,那是合情合理的。 Object提供的equals完成对那些类完全部都以不得不承认的表现。
  • 类无需提供八个“逻辑相等(logical equality)”的测验成效。举例java.util.regex.Pattern能够重写equals 方法检查多少个是或不是意味完全相仿的正则表明式Pattern实例,不过设计者并不以为顾客要求或期待采用此作用。在这里种气象下,从Object世襲的equals完成是最合适的。
  • 父类已经重写了equals方法,则父类行为完全切合于该子类。比如,大好些个Set从AbstractSet世襲了equals达成、List从AbstractList世襲了equals完毕,Map从AbstractMap的Map世襲了equals达成。
  • 类是私有的或包级私有的,能够明确它的equals方法恒久不会被调用。假如你可怜反感危害,能够重写equals方法,以作保不会被意向外调拨运输用:

    @Override public boolean equals(Object o) {
    throw new AssertionError(); // Method is never called
    }
    

那怎样时候须要重写 equals 方法吗?如果一个类满含八个逻辑相等( logical equality)的定义,此概念有别于对象标志(object identity),况兼父类还没有曾重写过equals 方法。那平时用在值类( value classes)的景况。值类只是叁个象征值的类,比方Integer或String类。程序员使用equals方法相比值对象的援引,期望发现它们在逻辑上是还是不是等于,并非援用相近的目的。重写 equals方法既可以够满意技师的盼望,它还扶持重写过equals 的实例作为Map 的键(key),恐怕 Set 里的要素,以满足预期和愿意的行事。

生龙活虎种无需equals方法重写的值类是应用实例调节(instance control)(条款1)的类,以承保每种值至多存在叁个对象。 枚举类型(条约34)归于那个类型。 对于这一个类,逻辑相等与对象标记是同风流倜傥的,所以Object的equals方法效果逻辑equals方法。

当你重写equals方法时,必需据守它的通用约定。Object的正式如下:
equals方法完毕了二个等价关系(equivalence relation)。它有以下那么些属性:
•自反性:对于任何非空援用x,x.equals(x)必需重回true。
•对称性:对于任何非空援引x和y,要是且仅当y.equals(x)返回true时x.equals(y)非得回到true。
•传递性:对于任何非空引用x、y、z,假诺x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)必须回到true。
•生龙活虎致性:对于任何非空援引x和y,要是在equals比较中采取的消息并未有改造,则x.equals(y)的高频调用必需始终重回true或风华正茂味再次回到false。
•对于其他非空援用x,x.equals(null)必须要重返false。

独有你开心数学,不然这看起来某个骇人听他们说,但不要忽视它!借使假定违反了它,很可能会发觉你的程序运维极度或崩溃,何况很难分明失败的来源于。套用John·Donne(JohnDonne卡塔尔国的说法,未有哪位类是孤立存在的。三个类的实例平常被传送给另三个类的实例。多数类,包含全数的集结类,都凭仗于传递给它们固守equals约定的对象。

既然已经开采到违反equals约定的摇摇欲倒,让大家详细地商量一下这几个约定。好消息是,表面上看,那实际不是很复杂。黄金时代旦您知道了,就一举成功遵从那大器晚成约定。

那么哪些是等价关系? 笼统地说,它是多少个运算符,它将豆蔻梢头组成分划分为相互成分相等的子集。 那个子集被叫作等价类(equivalence classes)。 为了使equals方法有效,各样等价类中的全体因素必需从客户的角度来讲是足以调换(interchangeable)的。 现在让我们挨个看下这几个多个须要:

自反性(Reflexivity)——第三个须要只是说一个目的必需与小编相等。 很难想象无意中违反了那几个规定。 假使您违反了它,然后把类的实例加多到四个集合中,那么contains格局或然会说集结中从未蕴含刚增添的实例。

对称性(Symmetry)——第二个须要是,任何三个对象必需在是还是不是等于的题目上实现生机勃勃致。与第三个须求区别的是,咱们简单想象在潜意识中违反了那蓬蓬勃勃渴求。比方,思虑上边包车型客车类,它完毕了不区分轻重缓急写的字符串。字符串被toString保存,但在equals相比较中被忽略:

import java.util.Objects;

public final class CaseInsensitiveString {
    private final String s;

    public CaseInsensitiveString(String s) {
        this.s = Objects.requireNonNull(s);
    }

    // Broken - violates symmetry!
    @Override
    public boolean equals(Object o) {
        if (o instanceof CaseInsensitiveString)
            return s.equalsIgnoreCase(
                    ((CaseInsensitiveString) o).s);
        if (o instanceof String)  // One-way interoperability!
            return s.equalsIgnoreCase((String) o);
        return false;
    }
    ...// Remainder omitted
}

地方类中的 equals 试图与常规的字符串进行操作,借使大家有二个不区分朗朗上口写的字符串和一个平常的字符串:

CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish”;

System.out.println(cis.equals(s)); // true
System.out.println(s.equals(cis)); // false

正如所料,cis.equals(s)返回true。 问题是,尽管CaseInsensitiveString类中的equals方法知情健康字符串,但String类中的equals方法却不经意了不区分朗朗上口写的字符串。 因而,s.equals(cis卡塔尔(英语:State of Qatar)重返false,显著违背对称性。 假若把一个不区分轻重缓急写的字符串放入三个汇聚中:

List<CaseInsensitiveString> list = new ArrayList<>();
list.add(cis);

list.contains(s)归来了怎么样?哪个人知道啊?在脚下的OpenJDK完毕中,它会再次回到false,但那只是三个兑现零构件。在另三个兑现中,它能够很容易地回到true或抛出运营时那些。生机勃勃旦违反了equals约定,就不亮堂其余对象在面临你的指标时会怎么着表现了。

要消灭这一个主题素材,只需删除equals方法中与String类相互操作的恶心尝试。那样做之后,可以将该方法重构为单个再次回到语句:

@Override
public boolean equals(Object o) {
    return o instanceof CaseInsensitiveString &&
            ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
}

传递性(Transitivity)——equals 约定的第一个必要是,要是第叁个对象等于第1个目的,第1个目的等于第八个指标,那么首先个对象必需等于第八个目的。同样,也轻易想象,无意中违反了那生机勃勃供给。思虑子类的情景, 将新值组件( value component)增多到其父类中。换句话说,子类增加了叁个新闻,它影响了equals方法比较。让我们从二个简单易行不可变的二维整数类型Point类起初:

public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (!(o instanceof Point))
            return false;
        Point p = (Point) o;
        return p.x == x && p.y == y;
    }

    ...  // Remainder omitted
}

假设想世袭那一个类,将象征颜色的Color类增添到Point类中:

public class ColorPoint extends Point {
    private final Color color;

    public ColorPoint(int x, int y, Color color) {
        super(x, y);
        this.color = color;
    }

    ...  // Remainder omitted
}

equals方法应该是什么体统?即使完全忽略,则达成是从Point类上长风破浪的,颜色音讯在equals方法相比中被忽视。就算那并不背弃equals约定,但那鲜明是不可承担的。假如你写了八个equals方法,它只在它的参数是另贰个独具同等地点和颜色的ColorPoint实例时回来true:

// Broken - violates symmetry!
@Override public boolean equals(Object o) {
    if (!(o instanceof ColorPoint))
        return false;
    return super.equals(o) && ((ColorPoint) o).color == color;
}

当您比较Point对象和ColorPoint对象时,能够会得到差别的结果,反之亦然。后面一个的可比大要了颜色属性,而后人的比较会直接返回false,因为参数的类型是大谬不然的。为了让难点进一层切实,我们创设二个Point对象和ColorPoint对象:

Point p = new Point(1, 2);
ColorPoint cp = new ColorPoint(1, 2, Color.RED);

p.equals(cp卡塔尔国重回 true,可是 cp.equals(p卡塔尔(英语:State of Qatar)再次来到false。你大概想选拔ColorPoint.equals 通过混合比较的措施来消除这些主题材料。

@Override
public boolean equals(Object o) {
    if (!(o instanceof Point))
        return false;

    // If o is a normal Point, do a color-blind comparison
    if (!(o instanceof ColorPoint))
        return o.equals(this);

    // o is a ColorPoint; do a full comparison
    return super.equals(o) && ((ColorPoint) o).color == color;
}

这种格局真的提供了对称性,不过丧失了传递性:

ColorPoint p1 = new ColorPoint(1, 2, Color.RED);
Point p2 = new Point(1, 2);
ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);

现在,p1.equals(p2)p2.equals(p3) 返回了 true,但是p1.equals(p3)却回到了 false,很声名远扬违反了传递性的必要。前五个相比较都以不思虑颜色音信的,而第多个比较时却隐含颜色音信。

别的,这种方法恐怕变成极端递归:要是有四个Point的子类,举例ColorPoint和SmellPoint,每一个都有这种equals方法。 然后调用myColorPoint.equals(mySmellPoint)将抛出叁个StackOverflowError非常。

那正是说建设方案是怎么着? 事实注明,那是面向对象语言中有关等价关系的二个主导难题。 除非你愿意吐弃面向对象抽象的补益,不然不可能持续可实例化的类,并在保留 equals 约定的同一时间加上五个值组件。

你恐怕据书上说过,能够持续多少个可实例化的类并增添叁个值组件,同一时候通过在equals方法中选拔二个getClass测量检验取代instanceof测验来保留equals约定:

@Override
public boolean equals(Object o) {
    if (o == null || o.getClass() != getClass())
        return false;
    Point p = (Point) o;
    return p.x == x && p.y == y;
}

惟有当对象具备类似的落实类时,才会时有产生相似的功力。那看起来可能不是那么不好,可是结果是不可负责的:一个Point类子类的实例仍为三个Point的实例,它依然要求作为一个Point来运作,不过风华正茂旦您采纳那一个主意,就能战败!固然我们要写二个办法来判断叁个Point 对象是或不是在unitCircle集结中。大家能够如此做:

private static final Set<Point> unitCircle = Set.of(
        new Point( 1,  0), new Point( 0,  1),
        new Point(-1,  0), new Point( 0, -1));

public static boolean onUnitCircle(Point p) {
    return unitCircle.contains(p);
}

即使那可能不是贯彻效果与利益的最快方法,但它能够健康专门的职业。借使以生龙活虎种不增加值组件的简便方法持续 Point 类,举个例子让它的布局方法追踪记录创设了稍微实例:

public class CounterPoint extends Point {
    private static final AtomicInteger counter =
            new AtomicInteger();

    public CounterPoint(int x, int y) {
        super(x, y);
        counter.incrementAndGet();
    }

    public static int numberCreated() {
        return counter.get();
    }
}

里氏代替原则( Liskov substitution principle)提议,任何项目的主要性性质都应该适用于具备的子类型,由此任何为这种类型编写的不二秘诀都应当在其子类上等同适用[Liskov87]。 那是大家前边扬言的四个职业汇报,即Point的子类(如CounterPoint)仍然为八个Point,必需作为三个Point类来对待。 但是,要是大家将一个CounterPoint对象传递给onUnitCircle方法。 如若Point类使用基于getClass的equals方法,则无论CounterPoint实例的x和y坐标如何,onUnitCircle方法都将回来false。 那是因为当先60%集合(包涵onUnitCircle方法应用的HashSet)都施用equals方法来测验是或不是含有成分,而且CounterPoint实例并不等于任何Point实例。 不过,假若在Point上接纳了妥善的根据instanceof的equals方法,则在动用CounterPoint实例显示时,同样的onUnitCircle方法能够健康办事。

虽说并未有中意的措施来持续多个可实例化的类并增多多少个值组件,可是有一个很好的变通方法:依照条文18的建议,“优先利用组合并不是后续”。代替世袭Point类的ColorPoint类,可以在ColorPoint类中定义四个民用Point属性,和一个共用的估量(view)(条款6)方法,用来回到具备同等地点的ColorPoint对象。

// Adds a value component without violating the equals contract
public class ColorPoint {
    private final Point point;
    private final Color color;

    public ColorPoint(int x, int y, Color color) {
        point = new Point(x, y);
        this.color = Objects.requireNonNull(color);
    }

    /**
     * Returns the point-view of this color point.
     */
    public Point asPoint() {
        return point;
    }

    @Override public boolean equals(Object o) {
        if (!(o instanceof ColorPoint))
            return false;
        ColorPoint cp = (ColorPoint) o;
        return cp.point.equals(point) && cp.color.equals(color);
    }

    ...    // Remainder omitted
}

Java平台类库中有部分类可以三番若干回可实例化的类并加多三个值组件。 举例,java.sql.Timestamp继承了java.util.Date并增添了八个nanoseconds字段。 Timestamp的等价equals确实违背了对称性,并且只要提姆estamp和Date对象在同七个聚聚集运用,恐怕以此外措施混合使用,则恐怕以致动荡的行事。 Timestamp类有八个豁免义务表明,告诫技士不要混用Timestamp和Date。 固然只要将它们分别使用就不会遇到麻烦,但未曾什么样能够阻碍你将它们混合在风度翩翩道,何况通过发生的错误可能很难调试。 Timestamp类的这种作为是二个荒谬,不应有被模仿。

您能够将值组件增添到抽象类的子类中,而不会违反equals约定。那对于经过遵从第25个条款中“优先构思类层级(class hierarchies)来替代标志类(tagged classes)”中的提出而获得的类层级,是那贰个紧要的。比如,能够有四个未曾值组件的抽象类Shape,子类Circle有三个radius属性,另叁个子类Rectangle富含length和width属性 。 只要不直接创制父类实例,就不会并发前边所示的题目。

生机勃勃致性——equals 约定的第八个供给是,假诺八个指标是格外的,除非贰个(或三个)对象被更改了, 那么它们必须始终维持相当。 换句话说,可变对象能够在分化不时候代能够与差别的对象相等,而不可变对象则不会。 当你写叁个类时,要认真思考它是不是应当设计为不可变的(条约 17)。 倘让你以为应当这么做,那么保证您的equals方法免强试行那样的限定:相等的靶子永恒相等,不等于的对象永世都不会等于。

无论是一个类是未为不可变的,都无须写一个信任于不牢靠财富的equals方法。 倘使背离那风流洒脱禁令,满足意气风发致性供给是充足不便的。 举个例子,java.net.U逍客L类中的equals方法信任于与UTucsonL关联的主机的IP地址的可比。 将主机名转换为IP地址可能须求拜候互联网,何况无法保障随着岁月的推移会时有产生相通的结果。 这大概会引致URubiconL类的equals方法违反equals 约定,并在执行中变成难题。 U锐界L类的equals方法的行为是二个超级大的谬误,不应该被模仿。 不幸的是,由于宽容性的供给,它不可能改换。 为了制止这种难题,equals方法应该只对内部存款和储蓄器驻留对象奉行鲜明性总结。

非空性(Non-nullity)——最终equals 约定的渴求未有法定的名号,所以自个儿冒昧地称呼“非空性”。意思是说说全数的对象都必得不对等 null。即使很难想象在调用 o.equals(null)的响应向往内地回去true,但轻易想象不当心抛出NullPointerException老大的情况。通用的预订禁绝抛出那样的丰裕。多数类中的 equals方法都会了然阻止对象为null的场馆:

@Override public boolean equals(Object o) {
    if (o == null)
        return false;
    ...
}

以此剖断是不供给的。 为了测验它的参数是不是等于,equals方法必得首先将其参数调换为方便类型,以便调用访谈器或同意访谈的特性。 在施行类型转变以前,该措施必得运用instanceof运算符来检查其参数是还是不是是正确的体系:

@Override public boolean equals(Object o) {
    if (!(o instanceof MyType))
        return false;
    MyType mt = (MyType) o;
    ...
}

若是此类型检查漏掉,并且equals方法传递了不当类型的参数,那么equals方法将抛出ClassCastException不行,那违背了equals约定。 可是,假如第叁个操作数为 null,则内定instanceof运算符再次回到false,而无论是第一个操作数中现身何类别型[JLS,15.20.2]。 因而,若是传入null,类型检查将赶回false,由此没有必要 分明的 null检查。

综合起来,以下是编制高水平equals方法的配方(recipe):

  1. 选取= =运算符检查参数是还是不是为该目的的引用。要是是,再次来到true。那只是大器晚成种属性优化,可是假诺这种比较恐怕超高昂的话,那就值得去做。
  2. 使用instanceof运算符来检查参数是还是不是具备无可争辨的档案的次序。 如若不是,则赶回false。 日常,准确的类别是equals方法所在的不得了类。 有时候,改类完毕了有个别接口。 若是类达成了一个接口,该接口能够改进equals约定以允许达成接口的类举办相比较,那么使用接口。 集结接口(如Set,List,Map和Map.Entry)具备此性子。
  3. 参数调换为科学的品类。因为更动操作在instanceof中已经管理过,所以它自然会成功。
  4. 对此类中的每一种“主要”的本性,请检查该参数属性是还是不是与该目的对应的属性相相称。假若具有那一个测量试验成功,重返true,不然再次来到false。如若手续第22中学的类型是八个接口,那么必得经过接口方法访谈参数的天性;借使类型是类,则足以一贯访谈属性,那取决属性的寻访权限。

对此项目为非float或double的宗旨类型,使用= =运算符举办相比;对于目的援用属性,递归地调用equals方法;对于float 基本类型的天性,使用静态Float.compare(float, float)情势;对于double 基本类型的性质,使用Double.compare(double, double)主意。由于存在Float.NaN-0.0f和相近的double类型的值,所以须求对float和double属性举办出格的拍卖;有关详细新闻,请参阅JLS 15.21.1或Float.equals方法的详尽文书档案。 就算您能够行使静态方法Float.equals和Double.equals方法对float和double基本类型的本性实行比较,那会变成每一次相比较时发出自动装箱,引发那些差的性能。 对于数组属性,将这个轨道应用于每种成分。 假设数组属性中的各个成分都很要紧,请使用个中一个重载的Arrays.equals方法。

有个别对象援引的属性大概合法地蕴涵null。 为制止现身NullPointerException格外,请使用静态方法 Objects.equals(Object, Object卡塔尔检查这一个属性是还是不是等于。

对于有个别类,譬喻上的CaseInsensitiveString类,属性比较相对于简单的相等性测验要复杂得多。在此种气象下,你想要保存属性的叁个正规格局( 佳能ical form),这样 equals 方法就足以依赖那一个专门的学业情势去做开荒相当的小的确切比较,来取代花销十分的大的非标准化准比较。这种方式实际最契合不可变类(条目17)。风姿罗曼蒂克旦目的产生转移,应当要作保把相应的正统方式创新到新型。

equals方法的质量恐怕蒙受质量比较顺序的影响。 为了获得最好品质,你应当率先比较最大概差异的习性,花销超小的性格,或然最佳是双方都满意(derived 田野先生s)。 你绝不相比不归属对象逻辑状态的质量,例如用于同步操作的lock 属性。 没有须求比较能够从“首要性质”计算出来的派生属性,不过这么做能够抓好equals方法的性情。 如若派生属性约等于对任何对象的摘要描述,比较那个天性将节省在相比较战败时再去相比较实在数据的开支。 比如,假设有一个Polygon类,并缓存该区域。 要是三个多边形的面积不等于,则无需费心比较它们的边和终极。

当你完结编制完equals方法时,问您自个儿八个难题:它是对称的吧?它是传递吗?它是同样的啊?除外,编写单元测量检验加以排查,除非采纳AutoValue框架(第49页卡塔尔国来生成equals方法,在这里种场合下得以自得其乐地总结测验。要是具备的品质失利,寻找原因,并相应地修改equals方法。当然,equals方法也必得满意别的多少个属性(自反性和非空性卡塔尔(英语:State of Qatar),但那八个属性凉常都会满意。

在底下这几个大致的PhoneNumber类中展现了依照早前的配方营造的equals方法:

public final class PhoneNumber {

    private final short areaCode, prefix, lineNum;

    public PhoneNumber(int areaCode, int prefix, int lineNum) {
        this.areaCode = rangeCheck(areaCode, 999, "area code");
        this.prefix = rangeCheck(prefix, 999, "prefix");
        this.lineNum = rangeCheck(lineNum, 9999, "line num");
    }

    private static short rangeCheck(int val, int max, String arg) {
        if (val < 0 || val > max)
            throw new IllegalArgumentException(arg + ": " + val);

        return (short) val;
    }

    @Override
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (!(o instanceof PhoneNumber))
            return false;

        PhoneNumber pn = (PhoneNumber) o;

        return pn.lineNum == lineNum && pn.prefix == prefix
                && pn.areaCode == areaCode;
    }

    ... // Remainder omitted
}

以下是局地终极指示:

  1. 当重写equals方法时,同一时候也要重写hashCode方法(条约 11)。
  2. 绝不让equals方法总括太精晓。假若只是简短地质度量试用于相等的性情,那么要坚决守护equals约定并不困难。假若您在寻找相等方面过于激进,那么十分轻便陷于麻烦。日常的话,思忖到其余款式的别称经常是三个坏主意。举例,File类不应有总计将引用的号子链接等同于同一文件对象。幸好File 类并没这样做。
  3. 在equal 时方法证明中,不要将参数Object替换到其余类型。对于程序猿来讲,编写贰个看起来像这么的equals方法并不菲见,然后花上几个小时苦苦构思为啥它无法健康工作:

    // Broken - parameter type must be Object!public boolean equals(MyClass o) {   
     …
    }
    

    难点在于那么些法子并未重写Object.equals方法,它的参数是Object类型的,那样写只是重载了 equals 方法(Item 52)。 就算除了常规的情势之外,提供这种“强类型”的equals方法也是不可选拔的,因为它或者会导致子类中的Override注脚爆发误报,提供不安全的错觉。
    在此,使用Override申明会阻止你犯这一个指鹿为马(条目款项40卡塔尔(英语:State of Qatar)。那一个equals方法不会编写翻译,错误音信会告诉您到底错在何地:

    // Still broken, but won’t compile
    @Override public boolean equals(MyClass o) {
    …
    }
    

    编写制定和测量试验equals(和hashCode卡塔尔国方法很麻烦,生的代码也十分不足为道。庖代手动编写和测量检验这么些方法的古雅的花招是,使用谷歌(Google卡塔尔(英语:State of Qatar)AutoValue开源框架,该框架自动为你生成这个点子,只需在类上添加四个解说就能够。在比非常多场合下,AutoValue框架生成的必定要经过的道路与您自身编辑的方式本质上是如出风华正茂辙的。

重重 IDE(举例 Eclipse,NetBeans,IntelliJ IDEA 等)也是有生成equals和hashCode方法的功能,不过变化的源代码比选用AutoValue框架的代码更软磨硬泡、可读性更差,不会自行跟踪类中的修改,因而需求进行测验。那便是说,使用IDE工具生成equals(和hashCode卡塔尔(قطر‎方法经常比手动编写它们更可取,因为IDE工具不会犯马虎大要的谬误,而人类则会。

总的说来,除非必需:在广大意况下,不要重写equals方法,从Object继承的兑现完全部是您想要的。 即使你真正重写了equals 方法,那么早晚要相比那几个类的兼具注重性质,並且以敬重后边equals约定里多个规定的法门去比较。

上一篇:并且拥有了巨大的品牌影响力 下一篇:没有了