Java Lambda表达式功能的混乱
我正在努力学习lambda表达式。我现在指的是OCP学习指南 在lambda表达式的一个示例中,有一个动物类和另一个名为CheckTrait的接口。lambda表达式的功能对我来说非常混乱。示例代码如下所示: 没有lambda表达式。Java Lambda表达式功能的混乱,java,lambda,java-8,Java,Lambda,Java 8,我正在努力学习lambda表达式。我现在指的是OCP学习指南 在lambda表达式的一个示例中,有一个动物类和另一个名为CheckTrait的接口。lambda表达式的功能对我来说非常混乱。示例代码如下所示: 没有lambda表达式。 public interface CheckTrait { public boolean test(Animal a); } public class Animal implements CheckTrait{ private String
public interface CheckTrait {
public boolean test(Animal a);
}
public class Animal implements CheckTrait{
private String species;
private boolean canHop;
private boolean canSwim;
public Animal(String species, boolean canHop, boolean canSwim) {
super();
this.species = species;
this.canHop = canHop;
this.canSwim = canSwim;
}
public boolean canHop() {
return this.canHop;
}
public String toString() {
return species;
}
public boolean canSwim() {
return this.canSwim;
}
@Override
public boolean test(Animal a) {
return a.canHop();
}
}
public class FindMathcingAnimals {
private static void print(Animal animal, CheckTrait trait) {
if(trait.test(animal)){
System.out.println(animal+" can hop" );
}else {
System.out.println(animal+" cannot hop");
}
}
public static void main(String[] args) {
Animal animal2= new Animal("Kangaroo", true, false);
print(animal2,animal2);
}
}
当我们运行上面的类时,我们得到的输出是袋鼠可以跳跃
带有lambda表达式
public interface CheckTrait {
public boolean test(Animal a);
}
public class Animal {
private String species;
private boolean canHop;
private boolean canSwim;
public Animal(String species, boolean canHop, boolean canSwim) {
super();
this.species = species;
this.canHop = canHop;
this.canSwim = canSwim;
}
public boolean canHop() {
return this.canHop;
}
public String toString() {
return species;
}
public boolean canSwim() {
return this.canSwim;
}
}
public class FindMathcingAnimals {
private static void print(Animal animal, CheckTrait trait) {
if(trait.test(animal)){
System.out.println(animal+" can hop" );
}else {
System.out.println(animal+" cannot hop");
}
}
public static void main(String[] args) {
Animal animal2= new Animal("Kangaroo", true, false);
print(animal2,s->s.canHop());
}
}
我的问题是,在下面一行
打印(animal2,s->s.canHop())
我没有给s传递任何值,只是传递一个表达式,那么程序是如何计算结果的呢?我知道它只是通过直觉获取动物对象并检查canhop变量,但我不理解这里的逻辑。请提供您的想法
编辑:根据Aominè的回答:
所以,我可以得出这样的结论。
在print方法中,我传递CheckTrait的行为,在print方法中,可以减少为:
步骤1:if(性状测试(动物)){
步骤2:if(s.canHop())
步骤3:if(动物canHop)
以上步骤仅供我理解。lambda表达式只是一个函数 形式
s -> s.canHop()
指定接收单个参数的函数,并对该参数调用canHop
函数
由于print
需要一个CheckTrait
,编译器知道参数的类型是Animal
我没有给s传递任何值,只是传递一个表达式,那么
计算结果的程序
下面,您将一个行为(函数)作为第二个参数传递给print方法,该方法将在print方法中使用
print(animal2, s -> s.canHop());
此函数的内容为“给定一个元素,例如s
,调用该元素上的canHop()
方法”
现在,在打印方法中执行以下操作时:
if(trait.test(animal)){ ... }
您正在调用trait.test(animal)并将动物对象传递给我们传入的函数,然后将该函数应用于输入动物
如果有帮助的话:
print(animal2,s -> s.canHop());
可被视为与以下内容相同:
print(animal2, new CheckTrait() {
@Override
public boolean test(Animal s) {
return s.canHop();
}
});
编辑:
正如您所提到的,方法调用可以看作:
if(trait.test(animal)){..} -> if(s.canHop()){..} -> if(animal.canHop){..} // pseudocode
我假设你不熟悉函数式编程,所以你可以这样看它-lambda就像一个缩写。基本上,
CheckTrait
是一个类,它包含一个方法,该方法接受一个Animal
,并返回一个布尔值,指示它是否具有cerain属性。它不执行任何外部操作或更改对于任何值或任何东西,它只是从另一个(动物)计算一个值(布尔值)。这是一个函数,在最纯粹的意义上
在旧版本的Java中,要创建表示CheckTrait
函数的对象,您必须这样做
CheckTrait canHop = new CheckTrait() {
public boolean test(Animal a) {
return a.canHop();
}
}
Animal a = ...;
canHop.test(a);
这需要输入很多内容,特别是因为这里唯一重要的细节是输入参数(animala
)和输出函数(returna.canHop()
)因此Java从函数式编程语言中借用了一种语法,在这种语言中,您可以只指定这两个元素,省去所有杂音,它会自动转换为上面的代码
CheckTrait canHop = (Animal a) -> { return a.canHop(); }
Animal a = ...;
canHop.test(a);
不过,这只适用于具有单个方法的接口。更好的是,他们这样做了,如果编译器可以猜测输入类型,并且函数只包含一个return语句,那么您可以省略该类型,甚至可以省略return
关键字
CheckTrait canHop = a -> a.canHop();
Animal a = ...;
canHop.test(a);
这就是lambda的工作原理。它们基本上是匿名类的缩写形式。
TLDR;
print(animal2,s->s.canHop())
是
print(animal2, new CheckTrait() {
public boolean test(Animal a) {
return a.canHop();
}
});
您可以将
s->s.canHop()
读作(动物s)->{return(s.canHop);}
。Java能够推断s
的类型,因为print(…)
需要一个动物
和一个CheckTrait
,将动物
映射到布尔值
,作为参数。感谢您的详细解释。请让我知道上述假设是否正确(如问题下方编辑部分所示)请注意,在本例中,您可以使用方法引用:print(animal2,s::canHop)
。