为什么该程序产生此结果?

时间:2018-07-25 09:21:04

标签: java lambda constructor java-8 method-reference

此处使用Lambda,但使用::new时,会将以下参数填充到构造函数中:

@FunctionalInterface
interface Lambdademo1<T> {
    T test(String s);
}

class Test {
    public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
        Apple i = lambdademo1.test(s);
        System.out.println(i.getColor());
    }

    public static void main(String args[]){
        test2(Apple::new,"hehehe");
    }
}

输出:

  

呵呵

更新:

class test {
    public static void main(String args[]) {
        test1((String s) -> new Integer(1), "hehehe");
        test1(Integer::new, "hehehe");  //It's wrong
        test2(Apple::new,"hehehe");
        test3(Apple1::new,"hehehe");    //Compile error
        // I think XXX::new is equivalen to new XXX() but here shoe  it's  not
    }

    public static void test1(Lambdademo1<Integer> lambdademo1, String s) {
        Integer i = lambdademo1.test(s);
        System.out.println(i);
    }

    public static void test2(Lambdademo1<Apple> lambdademo1, String s) {
        Apple i = lambdademo1.test(s);
        System.out.println(i.getColor());
    }

    public static void test3(Lambdademo1<Apple1> lambdademo1, String s) {
        Apple1 i = lambdademo1.test(s);
        System.out.println(i.getColor());
    }
}

Apple1类:

class Apple1 {
    private String color;
    // getter and setter
}

Apple类:

class Apple {
    private String color;

    public Apple(String color) {
        this.color = color;
    }
    // getter and setter
}

1 个答案:

答案 0 :(得分:4)

原始答案

Apple::new可以(并且确实)引用构造函数Apple(String),因为它遵循T test(String s)-(String string) -> new Apple(string);Apple:new

的约定

显然,由于getter返回您传递给构造函数的值,因此该构造函数为color字段设置了值。

test2(Apple::new,"hehehe");

等同于

System.out.println(new Apple("hehehe").getColor());

更新

让我们详细讨论每一行,以使其清楚。

1。

test1((String s) -> new Integer(1), "hehehe");

您正在使用String s,而不使用它,而是返回常量new Integer(1)或简单地返回1

我们可能会将其重写为

test1(s -> 1,"hehehe" );

2。

test1(Integer::new, "hehehe");

这没错。这是绝对可编译的行。有一个构造函数Integer(String s)使用String将给定的int转换为Integer.parseInt(String)

由于"hehehe"不是可解析的int,您将获得NumberFormatException,但这是运行时问题。

3。

很好,我已经在上面的原始答案中对此进行了解释。

4。

test3(Apple1::new,"hehehe");

您尚未为Apple1定义任何构造函数,因此默认情况下我们有一个无参数的构造函数。由于它不需要String,因此我们不能用它来表示Lambdademo1#test

尽管如此,编写lambda可以使其编译。

test3(s -> new Apple1(),"hehehe");
  

我认为XXX::new等同于new XXX(),但在这里不是。

这取决于上下文。 XXX::new始终引用 a 构造函数。什么构造函数?直到看到上下文,我们才知道。

检查一个示例,其中Apple::new指向3个不同的构造函数。

class Apple {
    public Apple() {}
    public Apple(Integer i) {}
    public Apple(String s) {}

    public static void main(String[] args) {
        Supplier<Apple> a = Apple::new;
        Function<Integer, Apple> b = Apple::new;
        Function<String, Apple> c = Apple::new;
    }
}