I was solving some questions for my OCA prepration. I found this problem at Oracle's website listing sample questions for exam.
public class MyStuff {
MyStuff(String n) { name = n; }
String name;
public static void main(String[] args) {
MyStuff m1 = new MyStuff("guitar");
MyStuff m2 = new MyStuff("tv");
System.out.println(m2.equals(m1));
}
public boolean equals(Object o) {
MyStuff m = (MyStuff)o;
if(m.name != null) return true;
return false;
}
}
What is the result?
Answer is-
3. The output is "true" and MyStuff does NOT fulfill the Object.equals() contract.
I understand how, and why the output is true
, but what I am not getting is that How come it does not fullfill the Object.equals()
contract, and what exactly is a "Contract" in Java, and what if we don't abide by it?
The @Contract annotation is used for defining a contract that a method must meet. This lets the IDE find problems in methods which call methods that you have annotated. You can use this annotation not only for annotating your own code but also for other existing libraries.
Contracts enable specifying conditions that must hold true when the flow of runtime execution reaches the contract. If a contract is not true, then the program is assumed to have entered an undefined state. Rationale: Building contract support into the language provides: a consistent look and feel for the contracts.
A contract class is a public final class that contains constant definitions for the URIs, column names, MIME types, and other meta-data about the ContentProvider. It can also contain static helper methods to manipulate the URIs.
In object-oriented programming it is natural that the program parts are classes. The preconditions and the postconditions of the public methods in a class together form a contract between the class and its clients. It can be a serious matter if a contract is broken.
The equals method implements an equivalence relation on non-null object references:
- It is reflexive: for any non-null reference value x, x.equals(x) should return true.
- It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
- It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
- It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified. For any non-null reference value x, x.equals(null) should return false.
The below method doesn't fulfill this obligation For any non-null reference value x, x.equals(null) should return false.
public boolean equals(Object o) {
MyStuff m = (MyStuff)o;
if(m.name != null) return true;
return false;
}
This will throw a ClassCastException
, if o
is null
, it should ideally return false
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With