Get generic interface class object - java

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.

Related

Get the type of generic T

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.

does Java type erasure erase my generic type?

I've thought java erasure wipes generic types out in compile time however when i test it by myself i realized there are some information about generic types in Bytecode.
here is my test :
i wrote 2 classes:
import java.util.*;
public class Test {
List integerList;
}
and
import java.util.*;
public class Test {
List<Integer> integerList;
}
i compiled both classes and somewhere in generic class i saw this line
integerList{blah blah}Ljava/util/List;{blah blah}
Signature{blah blah}%Ljava/util/List<Ljava/lang/Integer;>;{blah blah}<init>
in non generic class :
integerList{blah blah}Ljava/util/List;{blah blah}<init>
so obviously i have generic information inside bytecode so what is this erasure thing ??
what is this erasure thing ??
Erasure is a mapping from generic to raw types. The common phrase "because of erasure" is essentially meaningless. What is significant are the specifications that use the mapping.
There are two interesting uses.
It's used to map method signatures from using generics to raw types. It is the raw-type signatures that used for overloading. This causes the vast majority of the problems with "erasure". For instance, you can't have two methods add(List<String>) and add(List<Integer>) in the same type. Overloading probably isn't a great idea, and there's not a great willingness to add this feature.
The type available for an instance of an object at runtime is the type it was created with erased. So if you cast to, say, (String) that will be checked at runtime, but if you cast to List<String> only the erasure of that type (List) will be checked. You can have the variables of type List<String> and List<Integer> point to exactly the same instance. In practice, you shouldn't be using casts (of reference types) in 1.5 and later.
Where practical, generic information is kept in class files and made available through reflection. So you'll find it on class definitions, supertypes, fields, methods, constructors, etc.
Some Generic type information is stored in Signature attributes . Refer JLS 4.8 and 4.6 and JVM spec 4.3.4. Read here:
Probably the most common complaint about generics in Java is that they are not reified - there is not a way to know at runtime that a List<String> is any different from a List<Long>. I've gotten so used to this that I was quite surprised to run across Neil Gafter's work on Super Type Tokens. It turns out that while the JVM will not track the actual type arguments for instances of a generic class, it does track the actual type arguments for subclasses of generic classes. In other words, while a new ArrayList<String>() is really just a new ArrayList() at runtime, if a class extends ArrayList<String>, then the JVM knows that String is the actual type argument for List's type parameter.
and Neal Gafter's blog.
This is one instance where accurate use of terminology actually matters: Bytecode is the instruction set of the Java Virtual Machine. A class file contains bytecode, but also information used for linking (field signatures, method signatures, ...), for the bytecode verifier, for the debugger, ...
Type erasure means that generic type informations is not translated into byte code; more specifically, all instances of a generic type share the same representation in byte code. Likewise, the dynamic type of an object the runtime keeps track of (as used by the cast and instanceof operators, and available through getClass()) is the same for all instances of a generic class, irrespective of any type parameters supplied in the source code.
Your experiment proves that generic type information is retained in the class file, more specifically, in the types of method and field signatures. That's unsurprising, because the signatures are actually used at compile time. The might also be used at link time, and are even accessible through the reflection api. The crucial difference is that they are the declared types of fields or methods, not the runtime types of actual objects.
That is, since Java 1.5 we must distinguish between a variable's declared type, and the runtime type of the object it refers to. The former supports generics, the latter does not. And yes, this means there isn't a one-to-one correspondence between compile time and runtime types.
Type info will be erased from here
integerList = new ArrayList<Integer>();
in the bytecode it will be equivalent to
integerList = new ArrayList();
and there is no chance to know in runtime from integerList object what was its compile time type.
Erasure means that generic typing is not incorporated in the byte code (when the list is created or used).
The signature you see is used just to indicate that the field is generic.

what is Generic . and how to make possible to get the generic type on runtime

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.

What are the exceptions to type erasure in Java?

I have seen it mentioned on some places online that in some situations it is possible to use the reflection API to get back information about generic data types which I thought would be lost through type erasure.
I am looking for complete list of the situations where type erasure is not complete i.e. something is still accessible via reflection. A Good list of examples and associated reflection code that can get at the generic types would be excellent.
UPDATE http://tutorials.jenkov.com/java-reflection/generics.html had exactly the examples I was looking for.
I think it just comes down to this:
No object instance stores any type information.
The classes, however, retain all their generic signatures (otherwise you could not have any generic type checking at compile time)
So, using reflection, you can read the generic type information for a given class.
Example:
class MyList extends ArrayList<MyObject>{}
List<MyObject> x = new MyList();
Reflection will tell you that this is a List of MyObject (because this information is compiled into the MyList class).
but
List<MyObject> x = new ArrayList<MyObject>();
Reflection will not tell you anything useful (because the ArrayList class knows nothing about MyObject).
The general idea is that if you create a named or anonymous class that is a subclass of a generic type with particular types for the type parameters, then the subclass is not generic and not subject to type erasure. Assuming that you can get hold of the Class object for the subclass, you can use reflection on that object to find out what the parameter types are.
When you think about it, this is not really an "exception" to the erasure rule. Rather, it is arranging that the class in question is not generic by explicitly reifying it.

How do you access Class object for generics?

How can I access Class object for Generics?
Currently, I am doing it this way:
List<String> list= new ArrayList<String>();
list.getClass();
Is this OK? Or, what should be the way?
That will return the same as ArrayList.class. Java generics erase the generic type at runtime; in other words, from "list" you'll never know the element type is String. There's a great FAQ on this at
http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
It is true that erasure makes it impossible to get the generic type info of a given object, since the generics is only held in the structure of the source code. However, this does not mean it's impossible to get generic type parameters and in many important cases (e.g. building interfaces to a given class/method) you are able to do this. If you get hold of a class' elements via reflection, you can get generic information about the declared types used.
For example, get hold of a java.lang.reflect.Method via reflection, and call e.g. getGenericReturnType() on it. This will return an instance of java.lang.reflect.Type, which can be simply a Class but could also be an instance of ParameterizedType or even WildcardType where appropriate. Both of these latter cases allow you to see the declared generic types. I am not aware of any particularly elegant way to handle this other than instanceof checks, but the information is there if you need it.
This can give information on the generics types of fields, of method parameters and return types, and of the class itself (both its own generic parameters and those of its superclass and implemented interfaces). This can be very useful if you need to do type-safe argument checking for generic methods in a reflective context.

Categories