just for the sake of correctness - WholeMessageHandler<T> does not need
to have Class<T> genericParam field and constructor param - anonymous
class which just wraps the lambda expression is good enough.
On 13/03/14 09:56, Pavel Bucek wrote:
Hi Remi,
thanks! I suspected that it would not be possible, but it is always
better to have the confirmation.
My context is slightly different, but the consequences are similar
like with the jackson library. Seems a little unfortunate to have the
possibility to use lambdas even on places where it cannot work - my
guess is that this will become one of most frequent question on some
mailing lists..
(you don't really need to read further)
I'm working on JSR 356 - Java API for WebSocket implementation and
there is an interface:
interface MessageHandler.Whole<T> extends MessageHandler {
void onMessage(T message);
}
And then there is a Session object, which has method "void
addMessageHandler(MessageHandler handler);". Obvious common use of
this method is:
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
public void onMessage(String message) {
// ...
}
});
I can see my IDE automatically offers me to transform this to lambda
expression (this is actually what worries me a little, because all
users will see that and do it - because why not - it seems to be
equivalent with anonymous class). When this suggestion is accepted,
previous statement is transformed into:
session.addMessageHandler((MessageHandler.Whole<String>) message -> {
// ...
});
which looks prettier, but just does not work and cannot work :/ I
guess we could provide wrapper class, something like:
public static class WholeMessageHandler<T> implements
MessageHandler.Whole<T> {
private final Class<T> genericParam;
private final MessageHandler.Whole<T> wholeMessageHandler;
protected WholeMessageHandler(Class<T> genericParam,
MessageHandler.Whole<T> wholeMessageHandler) {
this.genericParam = genericParam;
this.wholeMessageHandler = wholeMessageHandler;
}
public Class<T> getGenericParam() {
return genericParam;
}
@Override
public void onMessage(T message) {
wholeMessageHandler.onMessage(message);
}
}
and then, when user would want to use lambdas, do it with help of that
class:
session.addMessageHandler(new WholeMessageHandler<Main>(Main.class,
param -> System.out.println("234")));
so I can do this like a workaround, but anyway, the initial
recommendation of the IDE is bad enough to cause us lots of mailing
list traffic and explanations why is not possible to use lambda in
"native" fashion. Anyway - I'm not describing my pain just to share my
pain - if anyone have any suggestions how this can be solved, I'm all
ears; any reply would be greatly appreciated.
Thanks!
Pavel
On 12/03/14 19:42, Remi Forax wrote:
On 03/12/2014 07:12 PM, Pavel Bucek wrote:
Hello all,
I have an issue with getting generic parameter when using lambdas. I
can get the type when using anonymous classes.
code sample will be more descriptive than anything I would say, so.. :
public class Main {
public static interface A<T> {
public void method(T param);
}
public static void main(String[] args) {
final A<Main> anonClass = new A<Main>() {
@Override
public void method(Main param) {
System.out.println("234");
}
};
final A<Main> lambda = param -> System.out.println("234");
//following does not help.
// final A<Main> lambda = (A<Main>)param ->
System.out.println("234");
// output: Main.Main$A<Main>
System.out.println("$ " +
anonClass.getClass().getGenericInterfaces()[0]);
// output: interface Main$A ### generic type info
is already lost (no <Main>)
System.out.println("# " +
lambda.getClass().getGenericInterfaces()[0]);
// parameterized type from annon class
final Type t =
((ParameterizedType)anonClass.getClass().getGenericInterfaces()[0]).getActualTypeArguments()[0];
System.out.println("$ " + t);
// parameterized type from lambda
System.out.println("# " + "???");
}
}
I was not able to find any useful documentation or article about
this, so sorry if this is something common - feel free to RTM me
(with relevant link please).
Thanks and regards,
Pavel
As you have seen a lambda is not an anonymous class :)
A non-serializable lambda is more lightweight than an anonymous class
so the generic information that are transmitted from the bytecode to
the runtime (the lambda metafactory) are not kept inside the lambda
class (a lambda class may be shared by several different lambdas).
A serializable lambda keep these information because you need them to
deserialize a lambda but they are not publicly available
The current implementation encoded them in the bytecode and this
bytecode is not publicly available so unless you serialize the lambda
and serialize it by hand, you can not have access to these information.
So you can not use a lambda with frameworks like Jackson that use the
TypeReference idiom,
you can still use an anonymous class for that :)
cheers,
Rémi