preface

Previous article how to use Spring data binding well? The soul questioning session left a question about equals and Hashcode. Basic interview often run into the related problems, this is not a complicated problem, but a lot of friends suffer from that they two relations and constraints, so write this article for that alone, this article will gradually (through, for example, Let the memory and understanding more easily) illustrate these Let you worry some problems, Let ‘s go…

Interview questions

1. Why do we need equals when we have the == operator in Java?

Equals compares object addresses and equals compares object values

Let’s take a look at equals in the Object class:

public boolean equals(Object obj) {
    return (this == obj);
}
Copy the code

We see that equals also compares object addresses by ==, without helping us compare values. Object is definitely an “ancestor” in the Java world, and the == sign cannot be changed or overwritten. But equals is a method, which gives us the possibility to override equals to compare values:

@Override
public boolean equals(Object obj) {
    // Rewrite the logic
}
Copy the code

When you buy a new computer, each computer has a unique serial number. Normally, two identical computers are put in front of you. Would you say that because the serial number is different, these two computers are different?

If we say that two computers are the same, we usually compare their “make/size/configuration”, as in:

@Override
public boolean equals(Object obj) {
    returnBrand equal & size equal & configuration equal}Copy the code

When we encounter the above scenario, we need to override the equals method. This explains why the Java world has == and equals problems.

2. equalsEqual andhashcodeEqual to the problem

There are two questions you often come across about both:

  • Two objectsequalsEqual, then theyhashCodeEqual?
  • Two objectshashCodeEqual, then theyequalsEqual?

To illustrate the two conclusions, here’s an unfortunate example, just for memorization purposes, equals is compared to the spelling of a word; HashCode is like the sound of a word, in the same context:

They also pronounce /si/curliest, so hashCode is equal, which answers the first question:

Two objectsequalsEqual, then theyhashCodeMust be equal

The answer to the second question is,

Two objectshashCodeEqual, then theyequalsNot necessarily equal

Look at the Object class hashCode method:

public native int hashCode(a);
Copy the code

Go ahead and look at the comments for the method, explicitly stating the constraints on the method

There is also a constraint on overriding equals behind this result

3. Rewrite theequalsWhat are the constraints?

The constraint on overriding equals is also clearly stated in the comment for the equals method, which I’ll repeat here:

Red orange red green green blue purple, colorful Israel; Do re mi fa la, do re la la, do re mi fa la la, do re mi fa La La, do re mi Fa La La, do re mi Fa La la, do re mi Fa La la, do re mi Fa La la, do re mi Fa La la, do re mi Fa La La, do re mi Fa La La

4. When do we need to rewritehashCode?

To compare values, we override equals, but when do we override hashCode?

Usually whenever we override equals we override hashCode

Why is there such a constraint? If two objects are equal to equals, their hashCode must also be equal. Let’s see what happens if we just override equals and not hashCode. Here’s an example:

Define the student class and use the IDE to just generate equals for us:

public class Student {

	private String name;

	private int age;

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (o == null|| getClass() ! = o.getClass())return false;
		Student student = (Student) o;
		returnage == student.age && Objects.equals(name, student.name); }}Copy the code

Write test code:

Student student1 = new Student();
student1.setName("A soldier of the Sun arch");
student1.setAge(18);

Student student2 = new Student();
student2.setName("A soldier of the Sun arch");
student2.setAge(18);

System.out.println("Student1. Equals (student2) equals: + student1.equals(student2));

Set<Student> students = new HashSet<Student>();
students.add(student1);
students.add(student2);
System.out.println("Student Set length is:" + students.size());

Map<Student, java.lang.String> map = new HashMap<Student, java.lang.String>();
map.put(student1, "student1");
map.put(student2, "student2");
System.out.println(Student Map set length is: + map.keySet().size());
Copy the code

View the run result:

Student1. equals(student2) equals: true Student Set length: 2 Student Map length: 2Copy the code

Student1 and student2 are obviously two objects by Set and Map, because when you call their PUT (Set add, HashMap put), you check whether the hash value is equal. Open the JDK and check it out for yourself

So we continue to rewrite the Student class hashCode method:

@Override
public int hashCode(a) {
    return Objects.hash(name, age);
}
Copy the code

Rerun the above test to see the results:

Student1. equals(student2) equals: true Student Set length: 1 Student Map length: 1Copy the code

We get what we expect, which is why we usually override equals and why it’s best to override hashCode as well, okay

  • If you’re using Lombok, have you noticed that Lombok has only one @equalSandHashCode annotation instead of splitting it into @equals and @hashCode annotations? For more on Lombok, Also check out my previous article on the use of Lomok

  • In addition, when overriding methods are generated using IDE shortcuts, you will also see the two methods together instead of being separated like getters and setters

The above two points are invisible standard constraints, we hope that we also strictly abide by this standard, in order to prevent unnecessary trouble, there are various ways to remember, if you can not remember this word constraints, remember the above picture in your mind you will understand

5. Rewrite thehashCodeWhy is there always the number 31?

If you are careful, you may have noticed that the way I overwrote hashCode above is very simple, using the objects.hash method.

public static int hashCode(Object a[]) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}
Copy the code

Here 31 is used to compute the hash value of the object

How to make good use of Spring data binding? At the end of the article mentioned in HandlerMethodArgumentResolverComposite class has a member variable like this:

private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
			new ConcurrentHashMap<MethodParameter, HandlerMethodArgumentResolver>(256);
Copy the code

The Map’s key is MethodParameter. This class must override the equals and hashCode methods as well

@Override
public boolean equals(Object other) {
    if (this == other) {
        return true;
    }
    if(! (otherinstanceof MethodParameter)) {
        return false;
    }
    MethodParameter otherParam = (MethodParameter) other;
    return (this.parameterIndex == otherParam.parameterIndex && getMember().equals(otherParam.getMember()));
}

@Override
public int hashCode(a) {
    return (getMember().hashCode() * 31 + this.parameterIndex);
}
Copy the code

Why is the number 31 used to compute the hash value? Why does the String hashCode method select the number 31 as the multiplier

conclusion

If you’re still confused about equals and hashCode relationships and constraints, just follow the steps above to recall them, or better yet, look directly at the JDK source; In addition, it is a very good way to take out actual examples to verify. If you still have relevant question, can also leave a message to discuss.

Soul asking

  1. The Thread class is not overwrittenequalsMethod, you know what else you don’t need to rewriteequalsMethods?
  2. From above HandlerMethodArgumentResolverComposite class member variables defined in the Map, you notice what knowledge, such as final, ConcurrentHashMap, capacity person, why do you want to write? Can you explain why?

Welcome to continue to pay attention to the public account: “One soldier of The Japanese Arch”

  • Cutting-edge Java technology dry goods sharing
  • Efficient tool summary | back “tool”
  • Interview question analysis and solution
  • Technical data to receive reply | “data”

To read detective novel thinking easy fun learning Java technology stack related knowledge, in line with the simplification of complex problems, abstract problems concrete and graphical principles of gradual decomposition of technical problems, technology continues to update, please continue to pay attention to……