4

I asked some question about lambdas here Java: how to resolve generic type of lambda parameter?, but this one is a bit different.

I have the method signature:

public <P> void handle(Consumer<P> consumer) {
...
}

I can use it with lambda:

.<Integer>handle(p -> System.out.println(p * 2));

Can I somehow resolve that actual generic type? I mean I want to get Integer.class within that handle method.

BTW I can resolve the issue like this:

 public <P> void handle(Class<P> pClass, Consumer<P> consumer) {...}

 .handle(Integer.class, p -> System.out.println(p * 2));

But it doesn't look kosher, if we change the lambda to inline implementation.

Community
  • 1
  • 1
Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • No. Otherwise you might close that topic as one with many questions. They provide separete subjects and expect different answers – Artem Bilan May 26 '14 at 08:35
  • 1
    I'm not sure I see the difference between the two questions. – Evan Knowles May 26 '14 at 08:50
  • I also don't get it to be honest – Konrad Morawski May 26 '14 at 09:52
  • 1
    It is possible - you just need to grab a reference to the lambda before passing it into `handle` that way you can resolve the type argument for its class. Ex: `TypeResolver.resolveRawArgument(Consumer.class, lambda.getClass());`. See [TypeTools](https://github.com/jhalterman/typetools) for more usage info. – Jonathan Dec 08 '14 at 18:47
  • Thanks, @Jonathan, but it doesn't help me. Please, see how end-user code looks using my framework: https://spring.io/blog/2014/11/25/spring-integration-java-dsl-line-by-line-tutorial – Artem Bilan Dec 08 '14 at 19:05
  • 1
    @ArtemBilan - Another option is to do the type resolution from inside your handle method: `TypeResolver.resolveRawArgument(Consumer.class, consumer.getClass());` That should work. – Jonathan Dec 08 '14 at 19:19
  • Great! Thanks, @Jonathan, it works fine! I'll consider to use your solution for the next release – Artem Bilan Dec 08 '14 at 20:26
  • Glad it worked. Are you planning to add TypeTools as a spring-integration dependency or update spring's internal type resolver to do something similar? – Jonathan Dec 08 '14 at 20:59

1 Answers1

5

No, this is not possible.

You cannot get something like T.class, because generics are erased at runtime. You really need to pass in Class<T> to be able to get the class itself.

I also smell an XY-problem. Perhaps you really need the class type, but without further information, this smells a little bit.

skiwi
  • 66,971
  • 31
  • 131
  • 216
  • Good. I accepted the answer and go ahead with the solution – Artem Bilan May 26 '14 at 09:10
  • 3
    Yes it **is** possible to recreate the value of T since it's captured in the bytecode as part of the lambda's method invocation. See [TypeTools](https://github.com/jhalterman/typetools) for an example. – Jonathan Dec 08 '14 at 18:44
  • Agree with @Jonathan, you can get the types, they are erased through the usual methods of getting types, however that doesn't mean they are fully erased at runtime, they are still present and can be got through different means, e.g. https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/core/GenericTypeResolver.html – Will Sep 04 '17 at 12:15