Overriding “equals” method: how to figure out the type of the parameter?

前端 未结 9 1294
栀梦
栀梦 2021-02-05 07:47

I\'m trying to override equals method for a parameterized class.

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return t         


        
相关标签:
9条回答
  • 2021-02-05 08:13

    I just ran into this problem myself, and in my -particular- case, I didn't need to know the type E.

    For example:

    public class Example<E> {
        E value;
    
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Example<?> other = (Example<?>) obj;
            if (value == null) {
                if (other.value != null)
                    return false;
            } else if (!value.equals(other.value))
                return false;
            return true;
        }
    }
    

    In the above code, there is no unchecked cast because of using Example<?>. The type parameter wildcard '?' saves the day.

    0 讨论(0)
  • 2021-02-05 08:16

    You can do it by retaining a reference to Class<E> type. However, in my opinion, equality tests should be about the values the objects represent rather than the concrete types the values get expressed.

    A classic example of this is the Collections API for example. new ArrayList<String>().equals(new LinkedList<Object>()) returns true. While these have completely different types, they represent the same value, namely "an empty collection".

    Personally, should two Tuples that represent the same data (e.g. ("a", "b")) be not equal, because one is of type Tuple<String> while the other is Tuple<Object>?

    0 讨论(0)
  • 2021-02-05 08:17

    Use reflection. http://tutorials.jenkov.com/java-reflection/generics.html

    0 讨论(0)
  • 2021-02-05 08:24

    Off-topic - do you realise that according to your implementation, Tuple(a0, a1) is equal to Tuple(a1, a1)? I suspect that's not what you want...

    On-topic, as others have said, erasure makes this impossible. But you should reconsider why you want this - equality checking only happens at runtime, and generics are only compile-time. Conceptually, a variable has generic parameters, but an object does not. Thus when you're comparing the equality of objects, the generic parameters do not matter at all; you can't take any appropriate action based on them at runtime anyway.

    Object equality, and generic parameter co-/contra-variance, are two orthogonal concerns.

    0 讨论(0)
  • 2021-02-05 08:24

    I agree with the comments above, why does the class E need to be equal? and how do you want to treat subclasses of E?

    Anyway, given that here is a code sample that may help you:

    public class Example<T> {
    
      T t;
    
      public Example(T t) {
        this.t = t;
      }
    
      public static void main(String[] args) {
        final String s = "string";
        final Integer i = 1;
        final Number n = 1;
    
        final Example<String> exampleString = new Example<String>(s);
        final Example<Integer> exampleInteger = new Example<Integer>(i);
        final Example<Number> exampleNumber = new Example<Number>(n);
    
        System.out.println("exampleString subclass "  + exampleString.t.getClass());
        System.out.println("exmapleIntger subclass " + exampleInteger.t.getClass());
        System.out.println("exmapleNumber subclass " + exampleNumber.t.getClass());
        System.out.println("Integer equals Number = " + 
            exampleInteger.t.equals(exampleNumber.t));
      }
    }
    

    You can call t.getClass() to get class information about the type of T (assuming it is not null, of course.)

    I hope this helps.

    0 讨论(0)
  • 2021-02-05 08:25

    Sadly, you can't do this at compile time; the information is gone. Such are the consequences of type erasure. An alternative is to store the parameter as a Class instance, and then look it up later.

    0 讨论(0)
提交回复
热议问题