import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
public class Testing {
public static void main(String[] args) {
List<B> list = new ArrayList<B>();
B b1=new B(); b1.setName("Durgesh");
B b2=new B(); b2.setName("Val");
list.add(b1);list.add(b2);
MyInterface<B> my1 = B :: printName;
my1.dummyDisplay(b1,b2);
MyInterface<B> my2 = (a,b) -> a.printName(b);
my2.dummyDisplay(b1,b2);
// MyInterface<B> my3 = b1::printName; //compilation error
}
}
class B{
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void printName(B b) {
System.out.println(this.name + b.name);
}
}
@FunctionalInterface
interface MyInterface <T> {
public void dummyDisplay(T s, T t);
}
即使 B 类的 printName 方法只接受 1 个参数,而 dummyDisplay 方法接受 2 个参数,下面的代码行也能正常工作。这是因为当我们使用 2 个参数调用 dummyDisplay(功能接口)方法时,编译器使用一个参数调用 printName 方法,而另一个参数作为参数传递给 printName 方法。这意味着 (arg1).printName(arg2)。注意方法 printName 中“this”关键字的使用。所以请始终记住,在这种类型的方法引用中,要调用的方法的参数数量(printName)应该始终比方法中使用的参数数量少 1( dummyDisplay)的功能界面。
MyInterface<B> my1 = B :: printName;
my1.dummyDisplay(b1,b2);
我希望你理解这个概念。
现在来到下面的代码行。这段代码只是我们刚才讨论的方法引用的替换。在这里,由于在函数式接口中声明的方法有 2 个参数,所以我们必须并且必须在 lambda 表达式中使用 2 个参数(在本例中为 a 和 b)。然后a.printName(b) 将被写为接口方法(dummyDisplay)的定义。它直截了当。Lambda 表达式可以在任何提供功能接口的地方使用(当然)。
MyInterface<B> my2 = (a,b) -> a.printName(b);
my2.dummyDisplay(b1,b2);
现在来到最后一段代码。我们得到编译错误,因为编译器期望 B 类的 printName 方法中的参数数量与功能接口方法中的参数数量完全相同。通常这种方法引用仅用于调用任何接受一些参数并对接受的数据进行一些处理的任何类的任何随机方法。例如。比如说计算类中存在的加法/乘法/除法方法或比较器功能接口的比较方法。在所有这些情况下,方法定义不使用“this”关键字。它只是接受一些参数并对它们执行一些任务。我希望你们能从中有所收获。
MyInterface<B> my3 = b1::printName; //compilation error
说了这么多,现在让我们来回答你的问题,
userList.forEach(User::printName);
工作正常,因为 forEach 方法在内部调用 Consumer 接口的方法 accept(arg1) 并且您的用户定义方法 printName 没有参数。所以按照我上面的解释,它是正确的,编译器不会抱怨。
和
userList.forEach(u1::printName);
给出编译错误,因为您在引用实例方法 printName 时使用了对象 u1 。因此编译器期望 printName 方法的参数数量与 Consumer 接口的 accept 方法中的参数数量相同。所以它会尝试从你的类 User 中找到 printName(User param1)。而且由于没有找到,编译器的抱怨也差不多。
我希望这对你们有帮助。如果我遗漏了什么或者我说错了什么,也请告诉我。