问题
I think this question is already somewhere out there, but I wasn\'t able to find it.
I don\'t understand, why it\'s necessary to have a functional interface to work with lambdas. Consider the following example:
public class Test {
public static void main(String...args) {
TestInterface i = () -> System.out.println(\"Hans\");
// i = (String a) -> System.out.println(a);
i.hans();
// i.hans(\"Hello\");
}
}
public interface TestInterface {
public void hans();
// public void hans(String a);
}
This works without problems, but if you uncomment the commented lines, it doesn\'t. Why? In my understanding, the compiler should be able to distinguish the two methods, since they have different input-parameters. Why do I need a functional interface and blow up my code?
EDIT: The linked duplicates didn\'t answer my question because I\'m asking about different method-parameters. But I got some really useful answers here, thanks to everyone who helped! :)
EDIT2: Sorry, I\'m obviously not a native speaker, but to precise myself:
public interface TestInterface {
public void hans(); //has no input parameters</br>
public void hans(String a); //has 1 input parameter, type String</br>
public void hans(String a, int b); //has 2 input parameters, 1. type = String, 2. type = int</br>
public void hans(int a, int b); //has also 2 input parameters, but not the same and a different order than `hans(String a, int a);`, so you could distinguish both
}
public class Test {
public static void main(String...args) {
TestInterface i = () -> System.out.println(\"Hans\");
i = (String a) -> System.out.println(a);
i = (String a, int b) -> System.out.println(a + b);
i = (int a, int b) -> System.out.println(a);
i.hans(2, 3); //Which method would be called? Of course the one that would take 2 integer arguments. :)
}
}
All I\'m asking is about the arguments. The method name doesn\'t matter, but each method takes an unique order of different arguments and because of that, Oracle could have implemented this feature instead just making a single method possible per \"Lambda-Interface\".
回答1:
When you write :
TestInterface i = () -> System.out.println("Hans");
You give an implementation to the void hans()
method of the TestInterface
.
If you could assign a lambda expression to an interface having more than one abstract method (i.e. a non functional interface), the lambda expression could only implement one of the methods, leaving the other methods unimplemented.
You can't solve it by assigning two lambda expressions having different signatures to the same variable (Just like you can't assign references of two objects to a single variable and expect that variable to refer to both objects at once).
回答2:
The most important reason why they must contain only one method, is that confusion is easily possible otherwise. If multiple methods were allowed in the interface, which method should a lambda pick if the argument lists are the same ?
interface TestInterface {
void first();
void second(); // this is only distinguished from first() by method name
String third(); // maybe you could say in this instance "well the return type is different"
Object fourth(); // but a String is an Object, too !
}
void test() {
// which method are you implementing, first or second ?
TestInterface a = () -> System.out.println("Ido mein ado mein");
// which method are you implementing, third or fourth ?
TestInterface b = () -> "Ido mein ado mein";
}
回答3:
You seem to be looking for anonymous classes. The following code works:
public class Test {
public static void main(String...args) {
TestInterface i = new TestInterface() {
public void hans() {
System.out.println("Hans");
}
public void hans(String a) {
System.out.println(a);
}
};
i.hans();
i.hans("Hello");
}
}
public interface TestInterface {
public void hans();
public void hans(String a);
}
Lambda expressions are (mostly) a shorter way to write anonymous classes with only one method. (Likewise, anonymous classes are shorthand for inner classes that you only use in one place)
回答4:
You do not have to create a functional interface in order to create lambda function. The interface allow you to create instance for future function invocation.
In your case you could use already existing interface Runable
Runnable r = () -> System.out.println("Hans");
and then call
r.run();
You can think of lambda ->
as only short hand for:
Runnable r = new Runnable() {
void run() {
System.out.println("Hans");`
}
}
With lambda you do not need the anonymous class, that is created under the hood in above example.
But this has some limitation, in order to figure out what method should be called interface used with lambdas must be SAM (Single Abstract Method). Then we have only one method.
For more detailed explanation read:
Introduction to Functional Interfaces – A Concept Recreated in Java 8
回答5:
Functional interface can only contain exactly one abstract method according to java specs.
Surely lambda expression can be one-time used as your commented code does, but when it comes to passing lambda expression as parameter to mimic function callback, functional interface is a must because in that case the variable data type is the functional interface.
For example, Runnable
is a built-in functional interface:
public interface Runnable() {
public void run();
}
The usage can be demonstrated as below:
public class LambdaTest {
// data type of parameter 'task' is functional interface 'Runnable'
static void doSeveralTimes(Runnable task, int repeat) {
for (int i = 0; i < repeat; i++) {
task.run();
}
}
public static void main(String[] args) {
// one-time lambda
doSeveralTimes(() -> {
System.out.println("one-time lambda");
}, 3);
// lambda as variable
Runnable test;
test = () -> {
System.out.println("lambda as variable");
};
doSeveralTimes(test, 3);
}
}
and the result is:
one-time lambda
one-time lambda
one-time lambda
lambda as variable
lambda as variable
lambda as variable
来源:https://stackoverflow.com/questions/33010594/why-do-i-need-a-functional-interface-to-work-with-lambdas