Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics: Comparing the class of Object o to <E>

Tags:

java

generics

Let's say I have the following class:

public class Test<E> {     public boolean sameClassAs(Object o) {         // TODO help!     } } 

How would I check that o is the same class as E?

Test<String> test = new Test<String>(); test.sameClassAs("a string"); // returns true; test.sameClassAs(4); // returns false; 

I can't change the method signature from (Object o) as I'm overridding a superclass and so don't get to choose my method signature.

I would also rather not go down the road of attempting a cast and then catching the resulting exception if it fails.

like image 687
SCdF Avatar asked Sep 09 '08 10:09

SCdF


People also ask

What is generic type E in Java?

For example, the type java. util. List<E> is a generic type: a list that holds elements of some type represented by the placeholder E . This type has a method named add() , declared to take an argument of type E , and a method named get() , declared to return a value of type E .

What is the difference between T and E in Java generics?

Well there's no difference between the first two - they're just using different names for the type parameter ( E or T ). The third isn't a valid declaration - ? is used as a wildcard which is used when providing a type argument, e.g. List<?>

Can we compare two objects in Java?

In Java, the == operator compares that two references are identical or not. Whereas the equals() method compares two objects. Objects are equal when they have the same state (usually comparing variables). Objects are identical when they share the class identity.


2 Answers

An instance of Test has no information as to what E is at runtime. So, you need to pass a Class<E> to the constructor of Test.

public class Test<E> {     private final Class<E> clazz;     public Test(Class<E> clazz) {         if (clazz == null) {             throw new NullPointerException();         }         this.clazz = clazz;     }     // To make things easier on clients:     public static <T> Test<T> create(Class<T> clazz) {         return new Test<T>(clazz);     }     public boolean sameClassAs(Object o) {         return o != null && o.getClass() == clazz;     } } 

If you want an "instanceof" relationship, use Class.isAssignableFrom instead of the Class comparison. Note, E will need to be a non-generic type, for the same reason Test needs the Class object.

For examples in the Java API, see java.util.Collections.checkedSet and similar.

like image 168
Tom Hawtin - tackline Avatar answered Sep 21 '22 03:09

Tom Hawtin - tackline


The method I've always used is below. It is a pain and a bit ugly, but I haven't found a better one. You have to pass the class type through on construction, as when Generics are compiled class information is lost.

public class Test<E> {     private Class<E> clazz;     public Test(Class<E> clazz) {        this.clazz = clazz;     }     public boolean sameClassAs(Object o) {         return this.clazz.isInstance(o);     } } 
like image 22
Nick Fortescue Avatar answered Sep 19 '22 03:09

Nick Fortescue