Generics and reflection

  • Thread starter chauvin.mathieu
  • Start date
C

chauvin.mathieu

Hi.

I would like to find, at run-time, the actual return type of a generic
method.
For a parameterized return type, that's OK, but what about a
TypeVariable return type ??

Suppose we have the following:

abstract class Generic<T> {
private T genericInstance;
public T getGeneric() {
return genericInstance;
}
public void setGeneric(T instance) {
genericInstance = instance;
}
}

// Recursive structure
class Concrete extends Generic<Concrete> {
}

The class Concrete actually defines a method which looks like:
public Concrete getGeneric();

But I just can't figure out, and I don't even know if it's possible,
how to find that this method returns an instance of Concrete.

Concrete.class.getMethod("getGeneric", null).getGenericReturnType()
returns a TypeVariable, and I just can't see how to do from it !

Thanks !

Mathieu
 
H

hiwa

(e-mail address removed) ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸:
Hi.

I would like to find, at run-time, the actual return type of a generic
method.
For a parameterized return type, that's OK, but what about a
TypeVariable return type ??

Suppose we have the following:

abstract class Generic<T> {
private T genericInstance;
public T getGeneric() {
return genericInstance;
}
public void setGeneric(T instance) {
genericInstance = instance;
}
}

// Recursive structure
class Concrete extends Generic<Concrete> {
}

The class Concrete actually defines a method which looks like:
public Concrete getGeneric();

But I just can't figure out, and I don't even know if it's possible,
how to find that this method returns an instance of Concrete.

Concrete.class.getMethod("getGeneric", null).getGenericReturnType()
returns a TypeVariable, and I just can't see how to do from it !

Thanks !

Mathieu
I think your code won't compile.
 
C

chauvin.mathieu

You may have to change one or two things (I wrote this code by hand),
but It does compile.

Well, actually, I think it's only possible to find the 'real' Type by
getting the generic superclass of Concrete, which is parameterized, and
then get the actual type.

Seems complicated !

hiwa a écrit :
 
C

Chris Uppal

The class Concrete actually defines a method which looks like:
public Concrete getGeneric(); [...]
Concrete.class.getMethod("getGeneric", null).getGenericReturnType()
returns a TypeVariable, and I just can't see how to do from it !

If you are interested in a concrete method of a concrete class, why are you
using getGenericReturnType() instead of getReturnType() ?

My advice (without knowing anything at all about your application) would be to
ignore generics entirely when doing reflection. Generics don't exist at
runtime, and reflection is an entirely runtime concept, so generics are
entirely irrelevant -- better to make your program work in terms of the /real/
types seen by the JVM, not the fake types dreamed up by the compiler.

-- chris
 
Z

Zaph0d

Please see
http://groups.google.com/group/comp.lang.java.programmer/msg/deaf0e48a4e9ae72

After reading and understanding that, I'll reiterate the gist that is
relevant to you:
_There is no way to determine the generic type in runtime_

What you can do is make your constructor something like this;
Class A<B> {
B b;
A(B b) {this.b = b;}
class returnGenericClass() { return b.class;}
String returnGenericClassName() { return b.class.name();} //or
something like that, look the api.
} //A

But someone could still do:
A<JComponent> = new A(JButton);
and you'll get "JButton" (or something like that).
(Sorry for the swing example, can't think of a simple, proper example
now).
 
C

chauvin.mathieu

Aren't things slightly different from your example, in that the
Concrete class *is not* generic, when your A class *is* ?
I think that the information that Concrete extends Generic AND that the
generic T is mapped to a Concrete type IS present in bytecode and CAN
be retrieved at run-time, even if it is complicated.
In my exemple, we can retrieve the fact that T is actually Concrete by
getting the generic superclass. It actually works, but I'm not sure
that it will be as simple, or even possible, when there are many
generic classes, more than one TypeParameters, ....
 
C

chauvin.mathieu

I don't use getReturnType() because it can only tell me that the method
returns a java.lang.Object (in my example).
It can be more accurate depending on the declaration of the generic
Class (class Generic<T extends SomeClass>), but it will never be the
actual return type for a subclass that binds T to something 'real' (I'm
not discussing an instance of the generic class, but really a
'concrete' subclass).

Chris Uppal a écrit :
 
P

Piotr Kobzda

I think that the information that Concrete extends Generic AND that the
generic T is mapped to a Concrete type IS present in bytecode and CAN
be retrieved at run-time, even if it is complicated.

Yes. You right.
In my exemple, we can retrieve the fact that T is actually Concrete by
getting the generic superclass. It actually works, but I'm not sure
that it will be as simple, or even possible, when there are many
generic classes, more than one TypeParameters, ....

For your example class it is possible, and is really simple:

((ParameterizedType) concreteClass.getGenericSuperclass())
.getActualTypeArguments()[0]

But in general, it is not easy (you have to analyze whole inheritance
tree) and sometimes it is simply useless:

class Concrete2 extends Concrete {}
class Concrete3<T> extends Generic<T> {}
class Concrete4<S, T> extends Generic<Concrete3<T>> {}
...

So I strongly suggest to forget about this concept. :)


If you really need to know the type of your class parameters, much
better solution is to directly provide class of this type parameters to
all interested classes, for example:

abstract class Abstract<T extends Abstract<T>> {
final protected Class<T> typeOfT;
protected Abstract(Class<T> typeOfT) {
this.typeOfT = typeOfT;
}
//...
}

with concrete classes like following:

class Concrete extends Abstract<Concrete> {
Concrete() {
super(Concrete.class);
}
}


piotr
 
C

Chris Uppal

[Please don't top-post -- it makes more work for every one else, including me]

(e-mail address removed) wrote:

[me:]
I don't use getReturnType() because it can only tell me that the method
returns a java.lang.Object (in my example).


You said earlier:
The class Concrete actually defines a method which looks like:
public Concrete getGeneric();

If that is true, then you shouldn't be getting a return type of Object, unless
you are looking at the wrong method.

IIRC, if you iterate over the methods of Concrete then you'll see two versions
of getGeneric(), one which actually overrides the one in the Generic superclass
(and which will return Object), and another with identical name and signature
but which returns Concrete. OTOH, if you just ask for the method with a given
name and signature then the reflection machinery will attempt to hide the gross
hacks the compiler has been performing and should just return the one which
returns Object.


-- chris
 
M

Mathieu

Chris said:
If that is true, then you shouldn't be getting a return type of Object, unless
you are looking at the wrong method.

There is only one version of getGeneric in my case.
The public Concrete getGeneric() method is *implicitly* defined because
my T type variable is bound to a Concrete in the definition of
Concrete.
I you iterate on all methods, you'll only see *one* getGeneric(),
returning Object, which declaring class is Generic, not Concrete.

Actualy, *it is* possible to retrieve information from reflection, but
it is simply not possible to get the actual type....
The reason is "simple": as a type variable may have many bounds, it is
only possible to get the actual types (with a 's' at the end......)

With the following:
public class Foo<T extends Serializable & Comparable<T>> {
public T getObject() {
return null;
}
}

What should we say about the return type of getObject ??? It is an
Object ? A Serializable ? A comparable ? It returns something that is
all of them !
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Trouble with reflection 0
Problem with reflection in C# 4
can this be done with generics? 32
Reflection 2
generics puzzle 57
Generics Issue 13
Generics 24
Generics ? 14

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,218
Latest member
JolieDenha

Latest Threads

Top