typetools
typetools copied to clipboard
TypeResolver.resolveRawArgument returns java.lang.Object instead of actual type ?
Hi;
I'm having (for example) the following interface:
public static class Printer<T> {
public void print(T t) {
...
}
}
Now, let's define a method reference on the "print" method, and using an instance of the Printer class:
Printer<String> printer = new Printer<>();
Consumer<String> print = printer::println;
Class<?> type = TypeResolver.resolveRawArgument(Consumer.class, print.getClass());
System.out.println(type); // prints "java.lang.Object" instead of "Printer" ?
so, above, I would expect to get a Printer type instead of Object ?
Notice that the following similar example is working fine:
Consumer<String> print = System.out::println;
type = TypeResolver.resolveRawArgument(Consumer.class, print.getClass());
System.out.println(type); // "java.lang.String"
Am I missing something ?
thanks in advance; /Pierre
I forgot to say that I'm using the following java version:
java -version
java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b17) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)
errata, (oops sorry):
for the following example:
Printer<String> printer = new Printer<>();
Consumer<String> print = printer::println;
Class<?> type = TypeResolver.resolveRawArgument(Consumer.class, print.getClass());
System.out.println(type);
I would expect the type to be "java.lang.String" instead of "Java.lang.Object".
thanks /Pierre
This seems to be similar to my #16?
I would explain this here that the object printer is taken as first parameter into the new created lambda expression printer::println as local variable. Then the TypeResolver finds the class both Printer and String share, which is Object.
Could this theory be true?
The short answer is that this use case does not appear to be supported by the technique we're using to resolve lambda type information. The reason is, with:
Printer<String> printer = new Printer<>();
Consumer<String> print = printer::println;
The argument for println is defined as String on the Printer<String> variable declaration. At runtime though, variable declarations are erased, so this just becomes Printer and the String is lost. It is similar to:
Consumer<String> print = System.out::println;
The difference is here the value of T is explicitly defined on the System.out.println method definition as a String rather than as T.
Hi,
I am facing this issue.
Consumer<Integer> c = System.out::println ; // not working it returns Object instead of Integer
work around is
Consumer<Integer> c = (Integer x) -> System.out.println(x);
Hi @yaitskov,
What's interesting about your scenario is that this works:
Consumer<String> print = System.out::println;
But this doesn't:
Consumer<Integer> print = System.out::println;
For whatever reason the ConstantPool, which is where we read lambda/method ref type information, encodes the latter scenario as println(Object o). It might be hard for us to recognize that in this scenario Object should actually be String since we're converting from another type. Perhaps we can detect that, but will need some further investigation.