IDEA generates `equals` and `hashCode` (for class ...
# announcements
g
IDEA generates
equals
and
hashCode
(for class
A
) with violating
hashcode
contract. Is it bug, or am I wrong?
k
what is contract of hashcode?
in theory it can be anything right?
g
one of the rules that hashcode must return equal hashes for equal objects
k
issue is in B hashcode right?
g
B doesn't violate any rules, A does
a
Defines what you mean by equality then for A, because it is vague since it has no state at all. And you call super.hashCode() which returns the virtual memory address for the Object class. Question related to A, because it has no state.
Copy code
val a1 = A()
val a2 = A()

val result = a1 == a2 // should this be true or false
if
result
should be true then you should implement hashcode for A as being something fixed and not return the virtual memory address (which is default behavior).
g
a1 == a2 must return false and it does
a
okay, so then I don't see what the issue is. B extends A and since every A is different every B will be also, regardless of the state. You explicitly let your hashcode of B depend on hashCode of A and since you say that the contract is that a1 != a2, the behavior is as expected.
Sorry, I am confusing A and B here....
g
I'm too))
b1 == b2 must return false
a
Copy code
val a1 = A(1);
val a2 = A(2);

val result = a1 == a2.
What must result be in your opinion?
g
false
a
ok, so everything is okay then right?
g
what do you mean by everything? Your code example?
IDEA generates wrong hashcode when superclass do override hashcode and don't equals
that's my point
a
Yeah I understand now
But hashcode is not related to equals
g
hashcode MUST relate to equals. It has contract written in documentation and a lot of books
a
But when reading the general contract of hashCode(): • Multiple invocations of hashCode() should return the same integer value, unless the object property is modified that is being used in the equals() method. • An object hash code value can change in multiple executions of the same application. • If two objects are equal according to equals() method, then their hash code must be same. • If two objects are unequal according to equals() method, their hash code are not required to be different. Their hash code value may or may-not be equal. It fails on the third requirement. You are right.
g
• If two objects are equal according to equals() method, then their hash code must be same.
I think the point is - "don't override hashcode without equals" or "don't trust generated code"🙂
a
I guess you are right
I guess the empty class
B
causes some issues here. I am trying some stuff out in IntelliJ.
g
yes it does
a
Copy code
open class B {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        return true
    }

    override fun hashCode(): Int {
        return javaClass.hashCode()
    }
}

class A(val i: Int): B() {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false
        if (!super.equals(other)) return false

        other as A

        if (i != other.i) return false

        return true
    }

    override fun hashCode(): Int {
        var result = super.hashCode()
        result = 31 * result + i
        return result
    }
}
This is what my IntelliJ generates for an empty class.
So here
B.hashCode
depends on the
javaClass
which is constant over different instances.
And so the contract is ok.
g
Copy code
if (!super.equals(other)) return false
this line also help
even if you didn't change my B class
it would be right
a
But your hashcode implementation is still broken which will cause issues with maps, sets, etc.
g
yeah, I'm wrong
m
I guess IDEA is technically wrong here - it should complain about the existing hashCode implementation in B. In any case, hashCode and equals should always be implemented together and be final.
a
But in my IntelliJ it works okay, so I guess it is a bug in a version?