C# allows for getting the type of generic parameters using the typeof(T)method without the need to instantiating the T parameter. But in Java anytime I have generic T parameter and I want to determine the type I have to create an instance of that parameter,for example by using the Class<T> Type, to figure out what type that is.
In comparison with what C# provides, this approach in Java looks unnecessarily lengthy and complicated.
I would like to know what is best alternative to determine the type of a generic parameter without the need to instantiate that (for example if (T is Integer)).
Generics in Java is a compile-time feature - thus the mismatch between Java and C#. As a result you cannot do anything at run time to determine the type unless you are either passed an object of the type or create one yourself or actually told the class in some other way.
It is generally considered a bad idea to even try to find the type. It generally indicates that you have not designed your class hierarchy properly.
Generics are compile-time true... but you can give the compiler hints of what t really is.
by passing in the actual runtime class of what T really is, you allow the compiler to allow you runtime knowlege of the class T represents.
example:
public <T> boolean isObjectT(Class<T> type, Object object){
return object.getClass().isAssignableFrom(type);
}
The answer on this question kinda spells out the limits of parameterized types:
Java: How do I specify a class of a class method argument?
If you are simply trying to get information from subclasses... you could try the reflection with paramterized types on this question:
How to determine the class of a generic type?
I have had good luck with that for more complex requirements.
Related
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.
Problem summary:
I would like to pass a class with a type parameter (such as ArrayList<SomeClass>, for example) to a generic method as a type parameter.
Let's say I have a method:
public static <T> T getGenericObjectFromJson(String json, Class<T> genericType){
// details unimportant, basically returns an object of specified type
return JsonParser.fromJson(json, genericType);
}
This method, of course, will work perfectly fine for any kind of class. I can call the method like so, for example:
getGenericObjectFromJson(jsonString, User.class)
The problem: I discovered I cannot do this:
getGenericObjectFromJson(jsonString, ArrayList<User>.class)
Syntactically, this is obviously invalid. However, I am not certain how I would even accomplish something like this. I can, of course, pass ArrayList.class, however the addition of the generic type makes it no longer syntactically valid, and I cannot think of a way around it.
The only direct solution has been something like this (which seems rather goofy):
getGenericObjectFromJson(jsonString, new ArrayList<User>().getClass())
However we end up losing the generic type anyways, and merely get back an ArrayList of unknown type (though it can be cast). Plus, unnecessarily instantiating an object.
My only solution thus far has been to wrap that method in a class that contains a generic type parameter which can be instantiated, like so:
public class JsonDeserializer<T>...
In this case, the getGenericObjectFromJson method will use the class's generic type.
The Question(s): Ultimately, I am curious why I cannot pass a class with a type parameter, AND whether there is a way to accomplish what I attempted to do.
As always, let me know if there are any problems with this question.
This is actually possible in Java, using some "tricks". Don't succumb to pressure from the C# fanatics! (j/k)
The "trick" is to create a class that extends a generic type, and access the value of the type parameter of the parent class through the Type returned by .getGenericSuperclass() or .getGenericInterfaces().
This is quite cumbersome. To simplify our lives, Google has already written most of the boring part of the code for us, and made it available through Guava.
Check the TypeToken class, which does exactly what you want. For example:
TypeToken<List<String>> stringListTok = new TypeToken<List<String>>() {};
Then you pass around a TypeToken<T> instead of a Class<T> and that's all. It provides you with methods to do reflection on the type represented by T.
What this is doing internally is simply calling .getClass().getGenericSuperclass() (or ...Interfaces()), then some ugly casts from Type to ParameterizedType and retrieving all the information from there (.getActualTypeArguments(), etc).
Finally, if you want to do something similar with Dependency Injection (ie, suppose you need to inject a Class<T> on the constructor of a class, or you want to get an instance of some parameterized interface, in which the instance should depend on the type parameter), Google Guice (a DI container from Google) has a very similar mechanism to solve the problem, called TypeLiteral. The use and the code behind the scenes are almost identical to TypeToken from Guava. Check it here: TypeLiteral
How can you determine what type of object a generic is using at runtime ?
Due to type erasure, you cannot determine the actual type parameter(s) of a generic object instance. The best you can do is set things up so you can pass a class object to code that needs to know the actual type. For example, this is what java.util.EnumMap does in one of its constructor.
If you mean the T in List<T> (for instance), you can't, because Java uses type erasure. At runtime, a List<T> just looks like a List. This is true except in the edge case of anonymous classes, where it's possible if you jump through hoops to find the parameter type. But in the general case, you cannot. You usually have to communicate that information separately.
First we explain What is Generic
Generic in Java is one of important feature added in Java 5,
From Oracle's documentation:
Generics were introduced to the Java language to provide tighter type
checks at compile time and to support generic programming. To
implement generics, the Java compiler applies type erasure to:
Replace all type parameters in generic types with their bounds or
Object if the type parameters are unbounded. The produced bytecode,
therefore, contains only ordinary classes, interfaces, and methods.
Insert type casts if necessary to preserve type safety.
Generate bridge methods to preserve polymorphism in extended generic types.
Type erasure ensures that no new classes are created for parameterized
types; consequently, generics incur no runtime overhead.
Now how to make possible to get the generic type on runtime, with the help of this link
read: http://www.west-wind.com/weblog/posts/2011/Nov/11/Dynamically-creating-a-Generic-Type-at-Runtime
It is not possible to get the object type of "Generics" at run time. If we use object.getclass(), so we can get object of any class with the class name.
class Json<T>
{
#SerializedName( "T's type here" )
private final ArrayList<T> _bucket = new ArrayList<T>( 5 );
...
}
I'd like to know how (if possible) the generic parameters of a class can be determined at run-time. From what I've read this is possible with sub-classes of generic types, but I haven't been able to find out how to do it with the type itself. There's some great info in these links, but I'm not sure it's what I'm looking for.
http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java
www.artima.com/weblogs/viewpost.jsp?thread=208860
What I'm ultimately trying to accomplish, is to get Gson to serialize the '_bucket' variable above, as the class name of type 'T'.
I'd appreciate it if someone could point me in the right direction.
The generic type is not available at runtime in the given example. Generic type information is only available via reflection if it was specified at compile-timeāfor example, if you defined a subclass SomeTypeJson extends Json<SomeType>.
As a kludge, you could guess at the generic type by examining the contents of the List, finding the most specific common superclass via reflection.
Typically you would sub-class this type to give concrete type, and then processing packages should be able to properly resolve type.
Alternatively many packages have a concept of type reference of some kind ("type token"), which just uses anonymous class to provide type information so that deserializer can correctly infer intended type; I don't remember what class Gson uses bit it should have something like this available.
If the only thing you have is a runtime instance then you are out of luck, with the exception of having non-empty List and checking its type (as suggested).
How to get class object of a generic interface?
For example, Boolean.class, Date.class.
But List<Boolean>.class doesn't seem to be syntax-valid.
Just write List.class. List<Boolean> is not of a different type, at runtime. The generic type only exists at compile time. So this imaginary List<Boolean>.class would not exist to be used in your program.
There is no way to programmatically access the generic type, since it is not present in the byte code. It is only to help the compiler.
Due to type erasure, your List<Boolean> will be converted to a simple raw List at runtime, thus, your best bet is to use List.class.