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.
Related
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).
I understand generics when it comes to collections. But what does it mean in the case of the Class<T> class? When you instantiate a Class object, there's only one object. So why the T parameter? What is it specifying? And why is it necessary (if it is)?
Type parameter <T> has been added to java.lang.Class to enable one specific idiom1 - use of Class objects as type-safe object factories. Essentially, the addition of <T> lets you instantiate classes in a type-safe manner, like this:
T instance = myClass.newInstance();
Type parameter <T> represents the class itself, enabling you to avoid unpleasant effects of type erasure by storing Class<T> in a generic class or passing it in as a parameter to a generic method. Note that T by itself would not be sufficient to complete this task2: the type of T is erased, so it becomes java.lang.Object under the hood.
Here is a classic example where <T> parameter of the class becomes important. In the example below, Java compiler is able to ensure type safety, letting you produce a typed collection from a SQL string and an instance of Class<T>. Note that the class is used as a factory, and that its type safety can be verified at compile time:
public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
Collection<T> result = new ArrayList<T>();
/* run sql query using jdbc */
for ( /* iterate over jdbc results */ ) {
T item = c.newInstance();
/* use reflection and set all of item’s fields from sql results */
result.add(item);
}
return result;
}
Since Java erases the type parameter, making it a java.lang.Object or a class specified as the generic's upper bound, it is important to have access to the Class<T> object inside the select method. Since newInstance returns an object of type <T>, the compiler can perform type checking, eliminating a cast.
1 SUN Oracle has published a good article explaining all this.
2 This is different from implementations of generics without type erasure, such as one in .NET.
3 Java Generics tutorial by Oracle.
The answer by dasblinkenlight already demonstrated one of the main uses of this parameter. There is one more aspect I consider relevant: using that parameter, you can restrict the kind of class you want to pass at a given location. So e.g.
Class<? extends Number> cls
means that cls may be any class implementing the Number interface. This can help catching certain errors at compile time, and makes class argument requirements more explicit.
Perhaps a comparison to the case without generics is in order
// Java ≥5 with generics // Java <5 style without generics
Class<? extends Foo> c; Class c;
Foo t1 = c.newInstance(); Foo t1 = (Foo)c.newInstance();
Object obj; Object obj;
Foo t2 = c.cast(obj); Foo t2 = (Foo)c.cast(obj);
As you can see, not having T as an argument would require a number of explicit casts, as the corresponding methods would have to return Object instead of T. If Foo itself is a generic type argument, then all those casts would be unchecked, resulting in a sequence of compiler warnings. You can suppress them, but the core issue remains: the compiler cannot check the validity of these casts unless you properly use the type argument.
In Java there's a single metaclass: Class. Its instances (only one per type exists) are used to represent classes and interfaces, therefore the T in Class<T> refers to the type of the class or interface that the current instance of Class represents.
The use of generics in the Class type is top define the type of class. If I have ' Class obj' my object obj can holds only children of Charsequence.
This is an optional argument. I'm often put an '?' to avoid warnings from the Eclipse IDE if I don't need an specific type of class.
I just learned about this fine looking syntax
Collections.<String>emptyList()
to get an empty List with elements which are supposedly of type String. Java's source looks like this:
public static final List EMPTY_LIST = new EmptyList<Object>();
:
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
Now if I code a method in that way where the generic type does not appear in the parameter list, is there any way how I can access the actual class that becomes T?
I'm saying, up to now my approach to code the same thing would have been
private <T> T get(String key, Class<T> clazz) {
// here I can do whatever I want with clazz, e.g.:
return clazz.cast(value);
}
If I removed the clazz-parameter I wouldn't be able to do the cast(). Obviously I could do
return (T) value;
but that gives me the usual warning Type safety: Unchecked cast from Object to T. Ok, #SuppressWarnings("unchecked") helps here, but actually I want to do something with the intended return type of the method. If I add a local variable
T retValue;
I'd have to initialise it with something, null doesn't help. After I assign it like
#SuppressWarnings("unchecked")
T retValue = (T) value;
I could do, e.g.
retValue.getClass().getName()
but if the cast fails I end up with no information about T again.
Since Java (or at least my Java 6) does not have the generic info any more during runtime, I currently can't think of a way to do this. Is there a way? Or do I have to stick with my "old" approach here?
Please note that the example I lined out is very simple and doesn't make much sense. I want to do more complicated stuff here, but that's out of the scope.
If you want the generic type at runtime you need to either have it as a field or create a sub-class of a type for a specific combination of types.
e.g.
List<String> list = new ArrayList<String>() {}; // creates a generic sub-type
final Class type = (Class) ((ParameterizedType) list.getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
System.out.println(type);
prints
class java.lang.String
You can't, unfortunately. All generics and type parameters are erased in runtime. So in runtime the type of your T is simply Object
retValue.getClass().getName() will always return the runtime type of the object and not the class name of the parameter type.
If you want to grab the parameter class, there's no other way than to use your first solution. (That is, pass the class object explicitly.)
As you mentioned, Java generics are build time only. They are not used at run time.
Because of this, the old approach you were using will be your only way to accomplish this.
I find out that there is one solution for getting Class<?> from T:
public class Action<T>{
}
public Class<?> getGenericType(Object action) throws ClassNotFoundException{
Type type =
((ParameterizedType)action.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
String sType[] = type.toString().split(" ");
if(sType.length != 2)
throw new ClassNotFoundException();
return Class.forName(sType[1]);
}
The usage of code above:
Action<String> myAction = new Action<String>();
getGenericType(myAction);
I did not tested this with primitive types (int, byte, boolean).
I think that it is not very fast, but you do not have to pass Class<?> to constructor.
EDIT:
The usage above is not right, because generic superclass is not available for Action<String>. Generic super class will be available only for inherited class like class ActionWithParam extends Action<String>{}. This is reason why I changed my mind and now I suggest to pass class parameter to constructor, too. Thanks to newacct for correction.
This question already has answers here:
When should I use the java 5 method cast of Class?
(5 answers)
Java Class.cast() vs. cast operator
(8 answers)
Closed 4 years ago.
I recently stumbled upon a piece of code that went like this:
Object o = .. ;
Foo foo = Foo.class.cast(o);
I was actually not even aware that java.lang.Class had a cast method, so I looked into the docs, and from what I gather this does simply do a cast to the class that the Class object represents. So the code above would be roughly equivalent to
Object o = ..;
Foo foo = (Foo)o;
So I wondered, why I would want to use the cast method instead of simply doing a cast "the old way". Has anyone a good example where the usage of the cast method is beneficial over doing the simple cast?
I don't think it's often used exactly as you have shown. Most common use I have seen is where folks using generics are trying to do the equivalent of this:
public static <T extends Number> T castToNumber(Object o) {
return (T)o;
}
Which doesn't really do anything useful because of type erasure.
Whereas this works, and is type safe (modulo ClassCastExceptions):
public static <T extends Number> T castToNumber(Object o, Class<T> clazz) {
return clazz.cast(o);
}
EDIT: Couple of examples of use from google guava:
MutableClassToInstanceMap
Cute use in Throwables#propagateIfInstanceOf, for type safe
generic throw spec
In Java there is often more than one way to skin a cat. Such functionality may be useful in cases where you have framework code. Imagine a method which accepts a Class object instance and an Object instance and returns the Object case as the class:
public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o)
{
SomeBaseClass castObj = whatToCastAs.cast(o);
castObj.doSomething();
}
In general, use the simpler casting, unless it does not suffice.
In some cases, you only know the type to cast an object to during runtime, and that's when you have to use the cast method.
There is absolutely no reason to write Foo.class.cast(o), it is equivalent to (Foo)o.
In general, if X is a reifiable type, and Class<X> clazz, then clazz.cast(o) is same as (X)o.
If all types are reifiable, method Class.cast() is therefore redundant and useless.
Unfortunately, due to erasure in current version of Java, not all types are reifiable. For example, type variables are not reifiable.
If T is a type variable, cast (T)o is unchecked, because at runtime, the exact type of T is unknown to JVM, JVM cannot test if o is really type T. The cast may be allowed erroneously, which may trigger problems later.
It is not a huge problem; usually when the programmer does (T)o, he has already reasoned that the cast is safe, and won't cause any problem at runtime. The cast is checked by app logic.
Suppose a Class<T> clazz is available at the point of cast, then we do know what T is at runtime; we can add extra runtime check to make sure o is indeed a T.
check clazz.isInstance(o);
(T)o;
And this is essentially what Class.cast() does.
We would never expect the cast to fail in any case, therefore in a correctly implemented app, check clazz.isInstance(o) must always succeed anway, therefore clazz.cast(o) is equivalent to (T)o - once again, under the assumption that the code is correct.
If one can prove that the code is correct and the cast is safe, one could prefer (T)o to clazz.cast(o) for performance reason. In the example of MutableClassToInstanceMap raised in another answer, we can see obviously that the cast is safe, therefore simple (T)o would have sufficed.
class.cast is designed for generics type.
When you construct a class with generic parameter T, you can pass in a
Class. You can then do the cast with both static and dynamic
checking, which (T) does not give you. It also doesn't produce unchecked
warnings, because it is checked (at that point).
The common sample for that is when you retrieve from persistent layer a collection of entity referenced with a Class Object and some conditions. The returned collection could contain unchecked objects, so if you just cast it as pointed G_H, you will throw the Cast Exception at this point, and not when the values are accessed.
One example for this is when you retrieve a collection from a DAO that returns an unchecked collection and on your service you iterate over it, this situation can lead to a ClassCastException.
One way to solve it, as you have the wanted class and the unchecked collection is iterate over it and cast it inside the DAO transforming the collection in a checked collection and afterwards return it.
Because you might have something this:
Number fooMethod(Class<? extends Number> clazz) {
return clazz.cast(var);
}
A "cast" in Java, e.g. (Number)var, where the thing inside the parentheses is a reference type, really consists of two parts:
Compile time: the result of the cast expression has the type of the type you cast to
Run time: it inserts a check operation, which basically says, if the object is not an instance of that class, then throw a ClassCast Exception (if the thing you're casting to is a type variable, then the class it checks would be the lower bound of the type variable)
To use the syntax, you need to know the class at the time you write the code. Suppose you don't know at compile-time what class you want to cast to; you only know it at runtime.
Now you would ask, then what is the point of casting? Isn't the point of casting to turn the expression into the desired type at compile time? So if you don't know the type at compile time, then there is no benefit at compile-time, right? True, but that is just the first item above. You're forgetting the runtime component of a cast (second item above): it checks the object against the class.
Therefore, the purpose of a runtime cast (i.e. Class.cast()) is to check that the object is an instance of the class, and if not, throw an exception. It is roughly equivalent to this but shorter:
if (!clazz.isInstance(var))
throw new ClassCastException();
Some people have mentioned that Class.cast() also has a nice return type that is based on the type parameter of the class passed in, but that is just a compile-time feature that is provided by a compile-time cast anyway. So for that purpose there is no point in using Class.cast().
I have been working on Google AdWords and came across this code
adwords-api-6.4.0, com.google.api.adwords.lib.AdWordsUser
public <T extends java.rmi.Remote> T getService(AdWordsService service) throws ServiceException {
try {
return (T) AdWordsServiceFactory.generateSerivceStub(service, this,
service.getEndpointServer(this.isUsingSandbox()), false);
} catch (ClassCastException e) {
throw new ServiceException("Cannot cast serivce. Check the type of return-capture variable.", e);
}
}
which is invoked like this:
AdWordsUser user = new AdWordsUser();
AdGroupServiceInterface adGroupService = user.getService(AdWordsService.V200909.ADGROUP_SERVICE);
Could you please explain how generics work in getService method? How is the return type determined?
What is the purpose of such usage? It doesn't seem like it provides type safety.
Does this usage have a specific name (so I could find more info on it and change the question title)?
A compiler may often infer the return type from the calling context. In the example provided, the compiler infers that the generic type is AdGroupServiceInterface because the result is being assigned to that type. If no context is available from which the return type can be inferred, it must be specified explicitly:
user.<AdGroupServiceInterface>getService(svc);
However, the getService method is not type-safe. Even though it contains a cast, this is only ensuring that the result implements the java.rmi.Remote interface. Because of type erasure in Java generics, the exact type T is not known, and the cast can't check to make sure that the result is AdGroupServiceInterface.
That's why a compiler will warn about the unsafe cast—a ClassCastException will be raised when the result is assigned to the AdGroupServiceInterface variable, not inside the method and its catch block.
I know more about C# than Java, but I'd guess that the getService method takes a parameter of type AdWordsService, and returns a type T, which must derive from java.rmi.Remote.
Presumably the AdWordsServiceFactory.generateSerivceStub method return type is of type java.rmi.Remote or similar, so it would be legal to cast this into the T type.
In C#, generics are used in this way to avoid casting, but the casting's still taking place here. I guess with this particular method, it's saving you from having to cast to your desired type, by making you tell the generic method exactly what type you want back.
I would also imagine that you need to specify the type of T in your call to getService. Maybe like this?
AdGroupServiceInterface adGroupService = user.getService<AdGroupServiceInterface>(AdWordsService.V200909.ADGROUP_SERVICE);