Java generic type comparison - java

I'd like to know if something like this is possible in Java (mix of C++ and Java ahead)
template<typename T> bool compare(Wrapper wrapper) {
if(wrapper.obj.getClass().equals(T.class))
return true
return false
}
To clarify, the function takes in an object which contains a java.lang.object, but I'd like to be able to pass that wrapper into this generic comparison function to check whether that object is of a particular type, ie
if(compare<String>(myWrapper))
// do x

No, it's not possible due to erasure. Basically, the compare method has no idea what T is. There's only one compare method (as opposed to C++, where there's one per T), and it isn't given any information about how it was invoked (ie, what the caller considered its T to be).
The typical solution is to have the class (or method) accept a Class<T> cls, and then use cls.isInstance:
public <T> boolean compare(Wrapper wrapper, Class<T> cls) {
return cls.isInstance(wrapper.obj);
}
// and then, at the call site:
if (compare(wrapper, Foo.class)) {
...
}
Of course, this means that the call site needs to have the Class<T> object. If that call site is itself a generic method, it needs to get that reference from its caller, and so on. At some point, somebody needs to know what the specific type is, and that somebody passes in Foo.class.

You cannot reference static members of a type parameter (such as you try to do in the form of T.class). You also cannot use them meaningfully in instanceof expressions. More generally, because Java generics are implemented via type erasure, you cannot use type parameters in any way at run time -- all type analysis is performed statically, at compile time.
Depending on exactly what you're after, there are at least two alternative approaches.
The first, and more usual, is to ensure that the necessary types can be checked statically. For example, you might parameterize your Wrapper class with the type of the object it wraps. Then, supposing that you use it in a program that is type-safe, wherever you have a Wrapper<String> you know that the wrapped object is a String.
That doesn't work so well if you want to verify the specific class of the wrapped object, however, when the class to test against is not final. In that case, you can pass a Class object, something like this:
<T> boolean compare(Wrapper<? super T> wrapper, Class<T> clazz) {
return wrapper.obj.getClass().equals(clazz);
}
That checks the class of the wrapped object against the specified class, allowing the method to be invoked only in cases where static analysis allows that it could return true.
You can actually combine those two approaches, if you like, to create a Wrapper class whose instances can hold only members of a specific class, as opposed to any object that is assignable to a given type. I'm not sure why you would want to do that, though.

Related

Can explicit type parameters redundant?

I have a class with a type parameter.
class MyObject<IdType> {
#Setter
#Getter
private IdType id;
}
And I thought I can add some method for conveniency so I did.
<T extends MyObject<? super IdType>> void copyIdTo(T object) {
object.setId(getId());
}
< T extends MyObject<? extends IdType>> void copyIdFrom(T object) {
object.copyIdTo(this);
}
And I just realized that I can do this.
void copyIdTo(MyObject<? super IdType> object) {
object.setId(getId());
}
void copyIdFrom(MyObject<? extends IdType> object) {
object.copyIdTo(this);
}
Are those two sets of methods are equivalent? Which way (or style) is prefer?
In your case, the two approaches are effectively equivalent. They both restrict the argument's type to MyObject<...> or a subtype.
Since your example methods return void there's no real benefit from making the method generic. The only important thing for your method is that the argument is a MyObject<...>—beyond that the real type is meaningless. Adding the ability to make the argument's type more specific adds nothing for the method's implementation and does nothing for the caller. In other words, it's irrelevant "fluff".
So for your examples, I would say prefer the non-generic option. It's cleaner and more straightforward.
However, if your methods returned the given argument back to the caller then making the method generic could prove useful; it would allow you to declare the return type as T. This opens up possibilities to the caller such as method chaining or invoking the method "inside" another method call, all based on the specific type passed as an argument. An example of this in the core library would be Objects.requireNonNull(T).
Another good case for making the method generic is mentioned by #Thilo in the comments:
Another case would be if your method takes multiple arguments. Then you can introduce a T to make sure those two arguments have the same type (instead of two distinct types that happen to [fulfill] the constraints individually).
Yes they are equivalent. Both sets of methods declare the same thing - that the method parameter must be of type MyObject<> or a compatible subtype (subclass).
The only reason to declare T in this way is if you need to refer to T elsewhere, such as the return type of the method, or if you have multiple parameters of the same type, or inside the method body.
I would always prefer the shorter, simpler, clearer version with less angle brackets to hurt the eyeballs :)

Can I do type inference in Java? Yes I can

I am an experienced C++ developer learning Java abstract concepts.
I was looking if I can do type inference in java and the answer is usually no and that I need to pass the Class type when calling a generic function. like so:
<T> void test(T t, Class<T> clazz);
I though this is redundant and that the compiler should be able to infer the type (C++ does it why can't Java :p) but then when I understood how generics are implemented under the hood I realized that T is essentially Object at runtime.
But then I realized that I can still call Object member functions on an instance of T. So I'm able to do something like this:
<T> void test(T t) {
if (t.getClass() == Integer.class ) {
// T is of type Integer.
}
}
1- Is there an advantage of either techniques over the other (i.e. passing Class<T> over checking Class type using getClass)?
2- Is there anything wrong with the second approach? The reason I am asking is that I have seen people go to the extend of using reflection and some obscure techniques before following what I've written above. Ideas?
There are a few issues here:
In general, you shouldn't really be inspecting the types of things at runtime. It's not wrong, per se, but if you feel the need to do it, then you're probably taking the wrong approach. For generics, for example, the whole point of a generic method is that it works regardless of the type argument.
Unlike C++, Java doesn't have any concept of template specialization; and Java programmers are comfortable with this restriction. Idiomatic Java code does not try to circumvent it.
There's no guarantee that t.getClass() is the same as the type T; t could be an instance of a subtype of T, for example. (Whereas a Class<T> is guaranteed to be the type T, unless it's null, or unless the program has "polluted the heap" by circumventing the generic type system.)
If you're going to do this, I'd suggest writing if (t instanceof Integer) instead of doing anything with getClass().
Is there anything wrong in the above approach?
Absolutely! If you have to "unmask" the generic type parameter T to do something special, you might as well do it in a separate piece of code, and either pass it on the side the way the class is passed, or require T implement a specific interface that provides the "special" functionality.
Is there an advantage of either techniques above over the other (i.e. passing Class<T> over checking Class type using getClass)?
Passing Class<T> technique has a specific reason behind it - letting you construct objects when you have none to begin with. In other words, it is applicable when you have no object on which to call getClass(), but you want to return an instance of T instead.

Define a generic type with a class object at runtime

Is it possible to declare the type of a generic using a class object?
For instance, I would like to do something like this:
Class returnType = theMethod.getReturnType();
AttributeComponent<returnType> attComponent;
attComponent = new AttributeComponent<returnType>(returnType, attName);
attributeComponents.put(methodName.substring(3), attComponent);
Now I know obviously this is incorrect, but is there a way to achieve this?
EDIT: explaining a little bit
I'm using reflection to go through all getters and then generate a UI element for each property (the AttributeComponent class, which has a JComponent element and a JLabel). I would like to use generics in order to create a getValue() method that would return an object of the property type.
I do not know if there is a way to compile something like that, but it has little value.
Think that thanks to type erasure, the compiled classes do not use the Generics information. That is, doing a Set<String> a = new Set<String>(); is useful for checking the use of a at compile time, but not at runtime.
So, you want to instantiate a Generic whose type will be only known at runtime, but at runtime it will not be used.
I would say this can be achieved by defining the method return type as generic; but you need to pass the actual type as a class argument to use it like you've shown:
<T> T yourMethod(Class<T> returnType) {
// use <T> as generic and returnType to refer to the actual T class
/* ... */ new AttributeComponent<T>(returnType, attName);
}
It would be also useful to see the larger context for what you're trying to do. If you want AttributeComponent.getValue() to return some generic type T (which is the method return type), that's completely useless unless you know each method return type at compile time, otherwise T will be nothing more than an Object. In my example above, you call yourMethod with a class that you already know and the same type will be returned (or some AttributeComponent of that type or whatever).

Proper use of Java Generics

I have the following function:
/**
* Finds all entities of a certain type
* #param <T> The type of the entity
* #param entityType The class of the entity
* #return A list of all the entities found, null if the entity is not in the database
* or on error
*/
public <T> List<T> findAll(Class entityType)
{
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityType));
return getEntityManager().createQuery(cq).getResultList();
}
You will note it is rather repetitive. Is there anyway that I can refactor this function so that it does not need to take a Class as a parameter. Is there anyway that I can use the generic type being passed in?
No, you cannot — directly. In a couple paragraphs I'll show you another way around the problem.
Java generics are implemented via type erasure, meaning that all type information is stripped away at runtime. When your method is invoked, it knows that it is supposed to return a List, but at run time there is nothing to tell it that it is supposed to return List<Foo>. The ArrayList constructor doesn't need access to the class object to do its job; your code, however, does.
The way around this is to just pass the class which, since this is a generic method (as opposed to a generic class), you can do. If you change the declaration of your method to be
public <T> List<T> findAll(Class<T> entityType)
Then you can call it with the class:
findAll(String.class)
and the compiler will automatically detect that it is supposed to return a List<String>. It reduces the redundancy, but by inferring the type argument from the class rather than the other way around. This is the standard way to solve this kind of problem — it shows up a lot in libraries like Guava.
The standard practice to create a "Generic DAO" is to have an abstract class that is parametrizable and have subclasses with a specific parameter. This way, the method itself is already parametrized with the correct type.
Take a look at this for an example:
http://netbeans.org/projects/samples/sources/samples-source-code/content/samples/javaee/AffableBean/src/java/session/AbstractFacade.java
Not really, no. Generics are a compile time feature. At run time a caller of your API can supply any instance of Class<T> for entityType so you need it available at runtime to provide to hibernate. The compiler has no ability to basically build a separate version of the method for every possible T, which is what it would have to do in order to omit the class parameter.
Also, Class is a raw type, you are already using generics improperly ;)
Java uses Type erasure, which means that the generic type parameter is not available at runtime (used at compile time to ensure your code is correct wrt to types). This means that to use persistence you will need to explicitly pass the class so the runtime can figure out how to do the persistence (e.g. what class the persisted object belongs to)
The simple answer is "no". Due to something called type erasure, all parameterized types are treated as Object.class at runtime in the compiled bytecode. The generic types are only used at compile time to prevent you from using things wrong.
You can more or less do what you're asking in Scala. (I'm not sure if you can use scala, but just for reference, here it is).
object Main extends App{
def findAll[T : Manifest]() : Array[T] = {
var a = new Array[T](0)
println(a.getClass)
a
}
var result = findAll[String]()
println(result.getClass)
var result2 = findAll[Array[Int]]()
println(result2.getClass)
}
By using the implicit Manfiest, the scala compiler keeps a record of what generics get erased on compile.

Generic method in Java, determine type

I would like to be able to detirmine the return type of my method call at runtime, but I can not seem to be able to get the Type of T.
public <T> T getT()
{
Object t = null;
Class<?> c = t.getClass();
System.out.println(c.getName());
return (T) t;
}
Is there any way to determine the Type of T at runtime in Java?
Your function will throw a NullPointerException, because you call "getClass" on a null pointer (since t is initialized with null). Additionally, generics are used for giving added compile-time type-checking. They do not give you anything special at runtime; generics simply use type Object, but cause the code which uses the generic object to perform implicit casts and also causes the compiler to be aware of how you will use it.
Java generics are a static type checking feature. Attempting to retrieve reflection artifacts from generic parameters is typical of poorly thought out design.
In the question example, there is no guarantee that T is a class or even interface. For example
List<? extends Frogs> list = thing.getT();
If you really want to go down this path (and I strongly suggest you don't, not that I expect you to take any notice), then you can supply a reflection object that is statically related to the generic parameter as an argument:
public <T> T getT(Class<T> clazz) {
Object value = map.get(clazz);
return clazz.cast(value);
}
If you have a generic Class you can write a constructor that takes the type and saves it into a member of your class. This way you can check the Type during runtime. All information that are only in the generics are gone after compiling.

Categories