Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Lambda表达式功能的混乱_Java_Lambda_Java 8 - Fatal编程技术网

Java 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

我正在努力学习lambda表达式。我现在指的是OCP学习指南

在lambda表达式的一个示例中,有一个动物类和另一个名为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->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)