3

Cannot convert functional interface with generic method into lambda expression.
Following code is working. It is without lambda expression i.e. using anonymous class.

public interface Pro{
    public <T> void callee(T t);
}

public void fun(Pro obj){}


public void implement() {
    fun(new Pro() {
        @Override
        public <Integer> void callee(Integer t){}
    });
}

I cannot understand how to use lambda expression instead of anonymous class.
After trying it myself I used the hint shown in netbeans. I used the shown bulb to do it.

enter image description here

And here is what I got, an ERROR.

public void implement() {
    fun((Integer t) -> {
    });
}

It is showing error. What is the correct lambda expression to be used here?
Here is the error :

one\LambdaScopeTest.java:18: error: incompatible types: invalid functional descriptor for lambda expression
    fun((Integer t) -> {
        ^
method <T>(T)void in interface Pro is generic
where T is a type-variable:
     T extends Object declared in method <T>callee(T)
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get
full output
afzalex
  • 8,598
  • 2
  • 34
  • 61
  • 2
    "It is showing error" is *never* enough information. What error, and where? – Jon Skeet Aug 11 '14 at 14:18
  • 1
    Funny how, IntellIJ IDEA does not suggest "Use lambda expression" but only the fact that with you hide Integer class. Suggested the replacement only after i generalize the interface and not the method. Netbeans was wrong with recognize possible replacement with lambda – Marco Acierno Aug 11 '14 at 14:28

1 Answers1

8

The main problem is that you've got a generic method instead of a generic interface. That doesn't make a lot of sense. As soon as you make the interface generic instead, it works:

@FunctionalInterface
interface Pro<T> {
    void callee(T t);
}

public class Test {    
    public static <T> void fun(Pro<T> obj){}

    public static void main(String[] args) {
        fun((Integer t) -> {});
    }
}

It makes much more sense for the interface to be generic, as then it makes sense to have different implementations for different types. For the method to be generic suggests that every implementation should be able to accept any value of any type, because the caller would be specifying it - which doesn't make sense if you then use a lambda expression with a specific type.

Your original version is only working because you're declaring a generic type parameter called Integer... you're not specifying an implementation for the Integer type. In other words, this:

fun(new Pro() {
    @Override
    public <Integer> void callee(Integer t){}
});

is equivalent to:

fun(new Pro() {
    @Override
    public <T> void callee(T t){}
});

... and I don't know of a way of representing that as a lambda expression. Basically, I think your original interface is inappropriate for lambda expressions.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I am sorry, but It is not my answer. – afzalex Aug 11 '14 at 14:27
  • @afzalex: What do you mean? Without any more detail, I can't help you any further. – Jon Skeet Aug 11 '14 at 14:28
  • @afzalex: As far as I'm aware, you can't use a lambda expression with your interface in its current form. Your interface needs to change, and your existing code probably doesn't mean what you think it means. – Jon Skeet Aug 11 '14 at 14:45
  • You have completely changed my question. I know it can work this way. But why it is not working when I am making function to be generic, not class – afzalex Aug 11 '14 at 14:48
  • @afzalex: I've shown you how to fix things, and explained why your original interface didn't make sense. Did you understand that the `Integer` in your original code *didn't* mean `java.lang.Integer`? I'm pretty sure the answer to your original question is "You can't." I was trying to be more helpful than that... – Jon Skeet Aug 11 '14 at 14:49
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/59115/discussion-between-afzalex-and-jon-skeet). – afzalex Aug 11 '14 at 14:51