Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

toString(), equals(), and hashCode() in an interface

So, I have an interface with a bunch of methods that need to be implemented, the method names are irrelevant.

The objects that implement this interface are often put into collections, and also have a special toString() format that I want them to use.

So, I thought it would be convenient to put hashCode(), equals(), and toString() into the interface, to make sure that I remember to override the default method for these. But when I added these methods to the interface, the IDE/Compiler doesn't complain if I don't have those three methods implemented, even though I explicitly put them in the interface.

Why won't this get enforced for me? It complains if I don't implement any of the other methods, but it doesn't enforce those three. What gives? Any clues?

like image 690
J_Y_C Avatar asked Nov 11 '09 21:11

J_Y_C


People also ask

Can we use equals method in interface?

If your interface contains other methods, Java will complain if you don't implement the interface fully by providing an implementation of those methods. But in the case of equals() , hashCode() and toString() (as well as a few others that you didn't mention) the implementation already exists.

What is the hashCode () and equals () used for?

The equals() and hashcode() are the two important methods provided by the Object class for comparing objects. Since the Object class is the parent class for all Java objects, hence all objects inherit the default implementation of these two methods.

What is toString and hashCode in Java?

equals() and hashCode() are majorly used to identify whether two objects are the same/equal. Whereas, toString() is used to Serialise the object to make it more readable in logs.

What is the relationship between hashCode () and equals () method in Java?

If two objects are equal(according to equals() method) then the hashCode() method should return the same integer value for both the objects. But, it is not necessary that the hashCode() method will return the distinct result for the objects that are not equal (according to equals() method).


Video Answer


1 Answers

It sounds like you want to force your classes to override the default implementations of those methods. If so, the way to do this is to declare an abstract superclass that has the methods declared as abstract. For example:

public abstract class MyBaseClass implements ... /* existing interface(s) */ {      public abstract boolean equals(Object other);      public abstract int hashCode();      public abstract String toString(); } 

Then change your current classes to extend this class.

This approach kind of works, but it is not an ideal solution.

  • It can be problematic for an existing class hierarchy.

  • It is a bad idea to force classes that implement your existing interface to extend a specific abstract class. For example, you can change parameters in method signatures to use the abstract class rather than the existing interface(s). But the end result is less flexible code. (And people can find ways to subvert this anyway; e.g. by adding their own abstract subclass that "implements" the methods with a super.<method>(...) call!)

  • Imposing a particular class hierarchy / implementation pattern is short sighted. You cannot predict whether some future requirement change will mean that your restrictions cause difficulties. (This is why people recommend programming against interfaces rather than specific classes.)


Back to your actual question about why your interface doesn't force a class to redeclare those methods:

Why won't this get enforced for me? It complains if I don't implement any of the other methods, but it doesn't enforce those three. What gives? Any clues?

An interface imposes the constraint that a concrete class implementing it has an implementation for each of the methods. However, it doesn't require that the class itself provides those methods. The method implementations can be inherited from a superclass. And in this case, that is what is happening. The methods inherited from java.lang.Object saftisfy the constraint.

JLS 8.1.5 states the following:

"Unless the class being declared is abstract, all the abstract member methods of each direct superinterface must be implemented (§8.4.8.1) either by a declaration in this class or by an existing method declaration inherited from the direct superclass or a direct superinterface, because a class that is not abstract is not permitted to have abstract methods (§8.1.1.1)."

like image 90
Stephen C Avatar answered Sep 23 '22 06:09

Stephen C