简体   繁体   中英

Why this Java Code is compiling successfully

I haven't overridden much of hashCode() and equals() methods so I may be wrong My question is for the last line where

dep1.equals(emp2) is being compiled successfully(why) (I am expecting compilation error as they have different types) and after compiling I get following

15   15    false

where I am expecting 15 15 true since I am checking the hashcode in the equals method.

class Employee {
    private String name;
    private int id;

    public Employee(String name, int id) {
        this.name = name;
        this.id = id;
    }


    public int hashCode() {
        return this.id; 
    }

    public boolean equals(Employee employee) {
        return this.hashCode() == employee.hashCode();
    }


    public int getEmployeeId() {
        return this.id;
    }
}

class Department {
    private String name;
    private int id;

    public Department(String name, int id) {
        this.name = name;
        this.id = id;
    }

    public int hashCode() {
        return this.id; 
    }

    public boolean equals(Department department) {
        return this.hashCode() == department.hashCode();
    }


    public int getDepartmentId() {
        return this.id;
    }
}


public class JavaCollections {
    public static void main(String args[]) {
        Employee emp2 = new Employee("Second Employee", 15);

        Department dep1 = new Department("Department One", 15);

        System.out.println(dep1.hashCode()+"  "+emp2.hashCode()+"  " + dep1.equals(emp2));
    }
}

First, for the reason why this compiles: all classes in Java inherit from java.lang.Object , which defines equals(Object) method, and provides a default implementation. This is the method that you call when you compare an Employee and a Department , not one of the overloads that you have provided.

Your equals code compiles fine, because the compiler does not know that you thought you were overriding equals when you actually didn't. The compiler thinks that you want to make a new method

public boolean equals(Department department)

to compare Department objects to other Department objects.

If you are writing a code that overrides a method of a superclass, add @Override annotation to it, like this:

@Override
public boolean equals(Department department)

Now the compiler will correctly complain to you that your method does not in fact override a method in its base class, alerting you to the problem at compile time.

To fix your code change the signatures of equals to take Object , add @Override , check for null and for the correct type, do the cast, and then do the actual comparison:

@Override
public boolean equals(Department obj) {
    if (obj == null || !(obj instanceof Department)) {
        return false;
    }
    Department dept = (Department)obj
    return dept.id == id;
}

Note: Implementing equals like this

return this.hashCode() == department.hashCode();

is very fragile. Although it works in your case, when hash code is a unique ID of the object, this wouldn't survive a code refactoring when hashCode is replaced with some other implementation, for example, an implementation that considers both id and name . If you want to rely on comparing IDs, compare IDs directly, without calling hashCode to get them.

That's because both of classes Employee and Department still have not overriden methods public boolean equals(Object obj) inherited from Object class.

Exactly this method is invoked in dep1.equals(emp2) , not public boolean equals(Department department) .

More specifically, read JLS :

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true: ... The signature of mC is a subsignature (§8.4.2) of the signature of mA.

In this case boolean equals(Department department) is not subsignature of boolean equals(Object obj) .

First, this code dep1.equals(emp2) calls default implementation of Object class.

Second, U didnt overrides the default implementation in both of your class becoz u cant override equal method for specific customizied types.

If u need ur answer to be 15 15 true

replace

public boolean equals(Department department) {
        return this.hashCode() == department.hashCode();
    }

by

@override
public boolean equals(Object department) {
        return this.hashCode() == department.hashCode();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM