How to solve this use case with gentyref

31 views
Skip to first unread message

Peter Niederwieser

unread,
Jan 4, 2010, 10:44:34 AM1/4/10
to gentyref
Say I have an object:

Object obj = new ArrayList<String>();

For some reason, I also have a declared type for the object:

Type type = new TypeToken<List<String>>(){}.getType();

Now, when reflecting on the object's fields and methods, I want to get
the best possible type information:

Method method = obj.getClass().getMethod("get", int.class);
Type returnType = GenericTypeReflector.getExactReturnType(method,
type);

This seems like a very natural use case to me, but gentyref doesn't
support this out of the box. The code only works if "method" is looked
up on List.class, but not if it's looked up on the object's type
(ArrayList). Is there a reason for this? Could gentyref be extended to
make this use case work?

Cheers,
Peter

Peter Niederwieser

unread,
Jan 5, 2010, 7:40:35 PM1/5/10
to gentyref
Let me put it differently:

Say I have a java.lang.Class representing ArrayList, and a
java.lang.reflect.ParameterizedType representing List<String>. Is
there a method in gentyref that, given these two values, will return a
ParameterizedType representing ArrayList<String>? Suppose I'm looking
for: ParameterizedType getExactSubtype(ParameterizedType type, Class<?
> subType)

Cheers,
Peter

Wouter Coekaerts

unread,
Jan 22, 2010, 4:07:28 PM1/22/10
to gent...@googlegroups.com
Hi,

> > Object obj = new ArrayList<String>();

> > Type type = new TypeToken<List<String>>(){}.getType();

> > Method method = obj.getClass().getMethod("get", int.class);
> > Type returnType = GenericTypeReflector.getExactReturnType(method,
> > type);

So you actually want the "get(int)" method from <type>, not from
obj.getClass(). But there is no direct way of getting a method from a Type.
So let's try to implement getMethod so that you can do:
Method method = getMethod(type, "get", int.class);

A first attempt, which works for your example, is just to take the erasure.
That'll always work if <type> is a Class or ParameterizedType like in your
example.
Method getMethod(Type type, String name, Class<?> parameterTypes) throws...{
return GenericTypeReflector.erase(type).getMethod(name, parameterTypes);
}

Something that'll work with more types is to look in all superclasses and
interfaces, and gentyref (at least the trunk) does have a method for that:
Method getMethod(Type type, String name, Class<?> parameterTypes) throws...{
for (Class<?> clazz :
GenericTypeReflector.getUpperBoundClassAndInterfaces(type)) {
try {
return clazz.getMethod("get", int.class);
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
}
}
throw ...;
}

On Wednesday 06 January 2010 01:40:35 Peter Niederwieser wrote:
> Let me put it differently:
>
> Say I have a java.lang.Class representing ArrayList, and a
> java.lang.reflect.ParameterizedType representing List<String>. Is
> there a method in gentyref that, given these two values, will return a
> ParameterizedType representing ArrayList<String>? Suppose I'm looking
> for ParameterizedType getExactSubtype(ParameterizedType type, Class<?>
> subType)

That's something different, and more difficult. Is the above solution enough,
or do you really want this?

Regards,

Wouter.

Peter Niederwieser

unread,
Feb 12, 2010, 4:33:01 PM2/12/10
to gentyref
On Jan 22, 10:07 pm, Wouter Coekaerts <wou...@coekaerts.be> wrote:

> That's something different, and more difficult. Is the above solution enough,
> or do you really want this?

Not sure why that's something different. What I want is to compensate
for erasure in cases where I know an object's static type. In pseudo-
code: unerase(dynamicType: ArrayList, staticType: List<String>) ==
ArrayList<String>.

Wouter Coekaerts

unread,
Feb 12, 2010, 5:59:01 PM2/12/10
to gent...@googlegroups.com

It's very different because your first question can be solved by looking for the method ("get") on the staticType (List<String>) using the "getMethod" from my previous mail. So it can be solved by just ignoring the dynamicType (ArrayList). But I guess that wasn't exactly what you were looking for, and you really want the other thing...

The general problem of trying to "unerase" something is really more advanced than what gentyref is doing.
What gentyref does now is like being a calculator: only (more or less) straightforward calculations. It doesn't really do anything except what the Java compiler itself does (but then at run-time instead of compile-time).
Unerasing on the other hand, is like solving a set of equations. And it goes further than the type-inference that the compiler does (and gentyref doesn't even do that).

The solution for such an equation can't always be expressed as a Java type. For example, take the following class:
class Foo<E> extends HashMap<E,E> {}
Now try to unerase(dynamic: Foo, static: HashMap<? extends A, ? extends B>)
The answer would be "Foo<X> with X a subtype of A and of B". Or "Foo<? extends A & B>" to have something close to Java syntax.
In other words, in general, the answer to an unerase can't be expressed as a type, only as a set of constraints (that you can try to simplify, which might or might not lead to a single type).

So I don't think this is a job for gentyref as it is now. Unless you can come up with a good way to represent such results and a not-too-complicated algorithm maybe...

Regards,

Wouter.



Reply all
Reply to author
Forward
0 new messages