That would allow the invoke method to have the right return type. For instance:
class Method<T> {
T invoke(Object obj, Object... args);
}
In Java, Generics are only available at compile time. You cannot determine the Generic type at runtime. This allowed the generics implementation to be backwards compatible with old versions of the JVM.
Since generics are only available at compile time, if you know the type of your class then you do not need to use reflection.
It would have been not unreasonable to make Method generic on erased return type. However, it would be a lot of effort with little gain. The nature of reflection is that you don't know the types at compile-time - otherwise you could statically link.
I guess you could in some case even add new APIs so that the generic type is returned. The information is still on the method, although not from the instance that you pass to it.
Related
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.
I have a method with the following signature:
<T> T getBody(Class<T> type)
that returns the body object as the specified type. How do I invoke it to return an object of type
Iterable<OProperty<?>>
I did a lot of Java before generics so my programmer fu is a little rusty in these circumstances :)
This can't be done with Class<T>. The only allowed T is a raw type because that is all that Class can be parametrized with (you can have Class<List> but not Class<List<String>>).
Class and generics doesn't work together very well. Class is for representing concrete runtime types, while generics is at compile time. We would like to have Class<Iterable> and Class<Iterable<Something>>, etc., but at runtime there is only one such object. No type for it would fit all of these uses. Java chose Class<Iterable>.
You can use some dubious unchecked casts to get the right type to pass to it:
getBody(Class<Iterable<OProperty<?>>>)(Class<?>)Iterable.class)
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.
It seems to me that Guice implementation is doing some very tricky things when dealing with generics. It looks like it knows at runtime about generic types used at compile time. Let's see a simple example:
#Inject
public void Bar(Provider<Foo> genericInjector){
...
At runtime Guice will inject a correct implementation of Provider here (i.e. the one that provides Foo instances). But from what I know, generic types are erased at runtime (see: Type Erasure ). So all that Guice really sees at runtime is:
#Inject
public void Bar(Provider genericInjector){
....
So how is it possible that Guice knows which implementation of Provider to inject?
No, type erasure doesn't erase everything. You can still get the types of fields, parameters etc. The Provider<Foo> information is still present at execution time. See Method.getGenericParameterTypes for example.
What isn't preserved is the type information about specific objects. For example, if I write:
List<String> list = new ArrayList<String>();
showType(list);
...
public static void showType(List<?> list)
{
// ???
}
There's no way that can work out that it's an ArrayList<String> because the object doesn't have that information any more.
See the Java Generics FAQ for a lot more information.
It is a common misconception that the way type erasure works is that the compiler essentially removes angle brackets and what's inside them and then acts as if the source was Java 1.4. This is not the case.
Generic parameters don't get erased from method signatures – method signatures are "compile-time". Generic parameters don't exist in "runtime" constructs – you can't tell what type parameters a given object was instantiated with.
this probably is a basic question, but can I do something like this:
Class myClass = Class.forName("Integer");
SomethingSimple<myClass> obj;
Where SomethingSimple is a very simple generic class:
class SomethingSimple<T>
{
T value;
SomethingSimple() {}
public void setT(T val)
{
value = val;
}
public T getT()
{
return value;
}
}
Obviously, the code above is not correct, since myClass is an object of type Class, and a class is required. The question is how can this be achieved. I read the other topics about Generics Reflection, but they concerned how the generic class knows the type.
No, you can't do that. What's the point? Generics give you compile-time type checking and if the class isn't known until runtime, you don't gain anything.
Generics in Java are used only for static type checking at compile time; the generic information is discarded after type checking (read about type erasure) so a SomethingSimple<Foo> is effectively just a SomethingSimple<Object> at runtime.
Naturally, you can't do comple-time type checking on a type that isn't known until runtime. The type has to be known to the compiler, which is why you have to use an actual type name rather than a Class variable as the generic type parameter.
Generics is a compile time mechanism to ensure type safety, and reflection is a runtime mechanism. What you're saying is, "I don't know at compile time what the type of T is but I want compile time type safety" (which doesn't make much sense). To put it another way, java erases the type of T at runtime and stores it as an Object...so the type of T (as far as generics are concerned) no longer matters.
But really it seems like you want a dependency injection container, like spring or google guise.