Lambda表达式功能混乱

时间:2017-12-23 12:30:21

标签: java lambda java-8

我正在尝试学习lambda表达式。我目前指的是OCP学习指南。

在lambda表达式的一个示例中,有一个Animal类和另一个名为CheckTrait的接口。 lambda表达式的功能对我来说非常混乱。示例代码如下所示:

没有lambda表达。

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.canHop());

我没有将任何值传递给s而只是表达式,那么程序如何计算结果呢?我知道它只是通过直觉获取动物对象和检查canhop变量,但我不理解这里的逻辑。请提供你的想法。

编辑:根据Aominè的回答:

那么,我能否得出结论。 在print方法中,我传递了CheckTrait的行为,并且在print方法中可以缩小为:

step1:if(trait.test(animal)){

第二步:if(s.canHop())

第3步:if(animal.canHop)

以上步骤仅供我理解。

3 个答案:

答案 0 :(得分:3)

  

我没有将任何值传递给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

答案 1 :(得分:0)

lambda表达式只是一个函数。

表格

s -> s.canHop() 

指定接收单个参数的函数,并在该参数上调用canHop函数。

由于print期望CheckTrait,编译器知道参数的类型为Animal

答案 2 :(得分:0)

我假设你不熟悉函数式编程,所以你可以这样看 - lambda就像一个缩写。基本上,CheckTrait是一个类,它包含一个方法,该方法接受Animal并返回一个布尔值,指示它是否具有cerain属性。它不会执行任何外部操作或更改任何值或任何内容,它只是从另一个(Animal)计算一个值(布尔值)。从最纯粹的意义上讲,这是一种功能。

在旧版本的Java中,要创建表示CheckTrait函数的对象,您必须这样做

CheckTrait canHop = new CheckTrait() {
    public boolean test(Animal a) {
        return a.canHop();
    }
}
Animal a = ...;
canHop.test(a);

这需要输入很多内容,特别是因为这里唯一重要的细节是输入参数(Animal a)和输出函数(return a.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; <{1}}是

的缩写
print(animal2,s->s.canHop())