Java 普通实例化和包含方法引用的实例化之间的差异
为什么在第一种情况下SomeClass只实例化一次,而在第二种情况下实例化n次,其中n是流中的元素数Java 普通实例化和包含方法引用的实例化之间的差异,java,java-8,java-stream,method-reference,Java,Java 8,Java Stream,Method Reference,为什么在第一种情况下SomeClass只实例化一次,而在第二种情况下实例化n次,其中n是流中的元素数 List<SomeClass> list = stream.map(new SomeClass()::method) .collect(Collectors.toList()); 和SomeClass.java: public class SomeClass { public SomeClass() {
List<SomeClass> list = stream.map(new SomeClass()::method)
.collect(Collectors.toList());
和SomeClass.java:
public class SomeClass {
public SomeClass() {
System.out.println(this);
}
public SomeClass method(Boolean b) {
return this;
}
}
因为在第一个代码段中,您只调用了一次
newsomeclass()
,因为:
List<SomeClass> list = stream.map(new SomeClass()::method)
.collect(Collectors.toList());
List List=stream.map(新的SomeClass()::方法)
.collect(Collectors.toList());
实际上等于:
SomeClass s = new SomeClass();
List<SomeClass> list = stream.map(a -> s.method(a))
.collect(Collectors.toList());
SomeClass s=newsomeclass();
List=stream.map(a->s.method(a))
.collect(Collectors.toList());
在实例
s
上调用方法method()
,在第一个代码段中,该实例只是没有保存到变量中,而是直接使用方法引用,方法引用只有四种类型(请参见中的“方法引用的类型”):
- 对静态方法的引用
- 对特定对象的实例方法的引用
- 对特定类型的任意对象的实例方法的引用
- 对构造函数的引用
newsomeclass()::methodName
属于第二类。它指的是一个特定对象的方法methodName
。该对象是新创建的SomeClass
对象。调用该方法时,它不会再创建任何SomeClass
对象,因为它是对新创建的特定SomeClass
对象的someMethod
的引用
另一方面,lambda表达式每次被调用时都会创建一个新的
SomeClass
,因为newsomeclass()
位于{…}
newsomeclass()
静态部分中,所以不会创建新对象,我想我无法重现这个问题。很明显,您丢失了一些信息。发布一个可验证的例子。我添加了一个复制的例子。这是一个错误的假设。它将被包装在一个方法体中。@ConcurrentBhai我不太明白你的意思。我错在哪里?方法体中包含了什么?“实际上等于这个”是绝对错误的<代码>新建SomeClass()::方法将被包装在方法体中。打开javap
查看它。@ConcurrentBhai,它们没有相同的密码。在第一种情况下,SomeClass
在调用lambda时实例化。在第二种情况下,它在创建方法引用之前被实例化。如果要将方法引用转换为lambda,必须首先在局部变量中捕获实例(如Lino的回答),然后将lambda声明为a->s.method(a)
。在等效代码中再次使用方法引用有点误导,因为这需要转换为等效代码(使用捕获的值)再次执行。最好在第二个代码中使用a->s.method(a)
。如果表达式不是一个new
操作,它永远不会null
,则等效代码类似于SomeClass s=Objects.requirennoull(表达式);…a->s.method(a)…
。你能告诉我第二类的作用域是什么吗?我的意思是,如果我有另一个具有相同逻辑的类,那么方法引用中的实例只创建了1或2个?@thang这与作用域无关,因为方法引用不是声明。我也不太理解你的第二个问题……你能给我看一些代码吗请说明您的意思?很抱歉,问题不清楚,如果我用相同的代码创建另一个类:List List=stream.map(new SomeClass()::method).collect(Collectors.toList());
。现在我们有两个类具有相同的方法引用。SomeClass()是否会用新实例创建?@thang是的,因为有两个new SomeClass()
立即呼叫。
List<SomeClass> list = stream.map(new SomeClass()::method)
.collect(Collectors.toList());
SomeClass s = new SomeClass();
List<SomeClass> list = stream.map(a -> s.method(a))
.collect(Collectors.toList());