设置对象等于彼此(java)

时间:2015-06-15 21:24:15

标签: java methods compiler-errors equals

所以我有一个名为Person的类,看起来像这样

public class Person {

    private String personName;


    public String toString(){
        return personName;
    }

    public Person(String personName){
        this.personName = personName;
    }

}

和我正在创建对象人的另一个类

public class IdanJavaTask {

    public static void main(String[] args) {

        Person p1 = new Person("Bob");
        System.out.println("p1 : " + p1);

        Person p2 = new Person("Joe");
        System.out.println("p2 :" + p2);

    }

}

到目前为止一切都很好,我的打印声明为
p1:鲍勃 p2:乔

现在我要创建一个新对象p3并将其设置为等于p1 我的课现在看起来像这样:

public class IdanJavaTask {

    public static void main(String[] args) {

        Person p1 = new Person("Bob");
        System.out.println("p1 : " + p1);

        Person p2 = new Person("Joe");
        System.out.println("p2 :" + p2);

        Person p3 = new Person (p1);
        System.out.println("p3 equal to p1:" + p3.equals(p1));

    }

}

当我尝试这样做时,我收到以下错误消息:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    The constructor Person(Person) is undefined

    at vehicleassignment.IdanJavaTask.main(IdanJavaTask.java:13)

我想我需要在main(Person)类中添加一个方法,但我不知道为什么或要添加什么?为什么我不能将对象设置为彼此相等?

5 个答案:

答案 0 :(得分:8)

有两种方法可以解释"将对象设置为彼此相等"。

一个是您希望p1p3引用相同的对象。就像Clark Kent和Superman是同一个人的两个名字(参考)一样。这将通过以下方式实现:

Person p1 = new Person("Jim");
Person p3 = p1;

在这种情况下,如果p1发生任何事情,p3也会发生同样的事情。如果你杀死克拉克肯特,你已经杀死了超人(因为他们是同一个人)。 Java使用equals(Object o)方法确定相等性 - 如果ab返回a.equals(b),则两个对象b.equals(a)true相等。使用基本Object平等定义,这两个对象将是相同的,因此您不必担心这一点。

解释你的意思的另一种方法是创建一个 new person对象,它恰好是第一个人的精确副本。为了做到这一点,你必须在你的person类中添加另一个构造函数,该构造函数将一个人作为参数:

public class Person {

    private String personName;

    public String toString(){
        return personName;
    }

    public Person(String personName){
        this.personName = personName;
    }

    public Person(Person personToCopy){
        this.personName = personToCopy.personName;
    }

}

通过此设置,您可以执行主要操作。

Person p1 = new Person("Bob");
Person p3 = new Person(p1); //Will have name Bob.

为了使p1p3相等,我们必须教Person类使用其字段来检查相等性。我们可以通过覆盖类人员中的equals方法来实现此目的。

public boolean equals(Object o){
    if(! (o instanceof Person)) return false; //a Person can't be equal to a non-person

    Person p = (Person) o;
    return personName == null && p.personName == null || personName.equals(p.personName);
}

每当我们覆盖equals方法时,最好还覆盖hashcode方法,该方法为每个对象返回唯一的int。由于Person对象所具有的唯一字段是其名称,因此我们可以简单地使用该哈希码。

public int hashCode(){
    return personName == null ? 0 : personName.hashCode();
}

总而言之,我们的Person类看起来像这样:

public class Person {

    private String personName;

    public String toString(){
        return personName;
    }

    public Person(String personName){
        this.personName = personName;
    }

    public Person(Person personToCopy){
        this.personName = personToCopy.personName;
    }

    public boolean equals(Object o){
        if(! (o instanceof Person)) return false; //a Person can't be equal to a non-person

        Person p = (Person) o;
        return personName == null && p.personName == null || personName.equals(p.personName);
    }

    public int hashCode(){
        return personName == null ? 0 : personName.hashCode();
    }
}

答案 1 :(得分:3)

Person p3 = new Person(p1);

这称为复制构造函数。在这种情况下,您需要明确定义它:

public Person(Person p) {
    this.personName = p.personName;
}

您还需要覆盖equals()方法(以及hashCode()方法)才能使用它,否则根类equals()的{​​{1}}方法将是used,总是返回false:

Object

请参阅What issues should be considered when overriding equals and hashCode in Java?

答案 2 :(得分:1)

Java中的任何对象都没有默认的复制构造函数,除了FloatInteger之类的自动装帧对象,这些对象确实被复制了。

这意味着在所有情况下,您都有责任在您的示例中定义复制构造函数并指定复制的内容:

public Person(Person other) {
  this.personName = other.personName;
}

因为在Java中,所有内容都通过引用传递,所以普通赋值只会使2个变量指向同一个实例,例如:

Person p1 = new Person("Joe");
Person p2 = p1;
// now both point to the same object, not intended behavior in your case

答案 3 :(得分:0)

如果您希望p3引用p2,意味着更改p2将更新p3,反之亦然,只需执行

Person p3 = p2;

如果你想克隆数据并拥有两个截然不同但相同的人物副本,你可以在Person中实现一个构造函数,它接受一个Person并将值复制到classes字段中。

答案 4 :(得分:0)

这是因为您的Person类构造函数。您将其定义为仅接受String类型,并在实例化它时为其指定了对象“ p1”。编辑构造函数或创建一个新的构造函数即可解决。