Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / September 2006

Tip: Looking for answers? Try searching our database.

Generics and reflection

Thread view: 
chauvin.mathieu@gmail.com - 07 Sep 2006 10:40 GMT
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
hiwa - 07 Sep 2006 10:59 GMT
chauvin.mathieu@gmail.com のメッセージ:

> Hi.
>
[quoted text clipped - 31 lines]
>
> Mathieu
I think your code won't compile.
chauvin.mathieu@gmail.com - 07 Sep 2006 11:08 GMT
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 :

> I think your code won't compile.
Zaph0d - 07 Sep 2006 11:44 GMT
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).
chauvin.mathieu@gmail.com - 07 Sep 2006 11:56 GMT
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, ....
Piotr Kobzda - 07 Sep 2006 19:02 GMT
> 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
Chris Uppal - 07 Sep 2006 11:20 GMT
> 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
chauvin.mathieu@gmail.com - 07 Sep 2006 18:20 GMT
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 :

> If you are interested in a concrete method of a concrete class, why are you
> using getGenericReturnType() instead of getReturnType() ?
[quoted text clipped - 6 lines]
>
>     -- chris
Chris Uppal - 08 Sep 2006 08:43 GMT
[Please don't top-post -- it makes more work for every one else, including me]

[me:]
> > If you are interested in a concrete method of a concrete class, why are
> > you using getGenericReturnType() instead of getReturnType() ?

> 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
Mathieu - 08 Sep 2006 14:36 GMT
> 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 !


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.