【问题标题】:Why is this program yielding this result?为什么这个程序会产生这个结果?
【发布时间】:2018-07-25 09:21:03
【问题描述】:

这里使用了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
}

【问题讨论】:

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


    【解决方案1】:

    原答案

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

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

    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) 使用Integer.parseInt(String) 将给定的String 转换为int

    由于"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;
        }
    }
    

    【讨论】:

    • @jwenting Apple 在这里不需要做任何事情——它的构造函数只是被其他人使用
    • @jwenting,是的,你需要定义一个符合接口的lambda或者匿名类,Apple本身不需要实现什么
    • @jwenting 到底是什么看起来很奇怪? :)
    • 有一个类实现依赖于同一个类的接口。对这个老大脑有循环依赖的味道(虽然我知道这不是真的)。​​
    • 基本上变成了“公共类Apple实现Demo
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-30
    • 2011-06-29
    相关资源
    最近更新 更多