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.
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 .
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<?>
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.
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.
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); } }
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