Java 8 方法引用默认方法实现

3
 interface HelloWorld {
    String hello(String s);
}
public static void main(String[] args) {
        HelloWorld h = String::new;
        System.out.println(h.hello("dasdasdadasd"));
}

当我执行上述方法时,它返回我在参数中传递的值dasdasdadasd。是执行了字符串类的哪个方法,还是Java在运行时提供了任何默认实现或默认调用supplier.get()方法?
2个回答

5
被分配了一个方法引用到String类的public String(String original)构造函数。这是唯一与您的HelloWorld接口的String hello(String s)方法匹配的构造函数。

因此,h.hello("dasdasdadasd")创建一个新的String实例,其值等于"dasdasdadasd"并返回该实例。

HelloWorld h = String::new;

等效于:

HelloWorld h = s -> new String(s);

我能理解。但是为什么它会打印我传递的参数呢?例如,如果我用 s->s.toUpperCase() 替换 String::new,那么它就会调用 String 类的 toUpperCase 方法,但是在 String::new 的情况下,它调用哪个方法呢? - Prasad
@PrasadReddy 它调用了 new String("dasdasdadasd"),它返回一个包含与原始字符串相同字符的新字符串。 - Eran
那么就像是使用传递的参数创建一个新的字符串对象并返回相同的对象,对吗? - Prasad
@PrasadReddy 它创建一个新的字符串对象并返回该新对象,这意味着它不会返回您传递给它的相同对象。 - Eran
@PrasadReddy,“在运行时提供”是什么意思?String类的public String(String original)构造函数已经在编译时存在。 - Eran
显示剩余7条评论

2
您的代码可以重写为:

hw返回一个由它接收到的内容创建的字符串:

//Returns a string based on the input
HelloWorld hw = (s) -> {
    return new String(s);
}; 

在该对象上调用hello()会返回“基本上”输入的内容:
//The value assigned to print is "dasdasdadasd", as returned by hw
String print = hw.hello("dasdasdadasd");

println正在接收dasdasdadasd

System.out.println(print); //"dasdasdadasd" is passed to println

@PrasadReddy 这里的lambda表达式以及String::new都是HelloWorld的实现。Java看到签名匹配,即HelloWorld是一个函数式接口,并且可以基于方法引用、lambda表达式等创建实现它的对象。查看java.lang.FunctionalInterface的javadoc,你会了解它是如何工作的。 - ernest_k
如果我的方法签名是 void hello(); HelloWorld h = Customer::new; h.hello(); 它提供了什么实现? - Prasad
我能够执行它。它没有报错吗? - Prasad
是的,那仍然有效。然后实现函数的类型是“Consumer”形式(1个参数void方法)。 - ernest_k
@PrasadReddy 如果你正在阅读有关Java 8和lambda表达式的函数式编程内容,那么你肯定会遇到这些内容。最好的查找位置是java.util.function包(https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html),还有很多在线文章,只需谷歌搜索“Java中的函数式编程”,就会发现大量内容... - ernest_k
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接