我已经阅读了IBM article,了解Java中的安全构造函数技术。本文的主要思想是,您不应在构造函数中显式或隐式公开 this 引用。但是没有提到关于lambdas。据我所知,lambda捕获局部上下文(仅最终或最终变量),因此,如果您在lambda体内引用任何类方法,那么这个引用会公开吗?
我的问题如下:设计在构造函数中接受Runnable
,Function
,Predicate
作为参数的类是一种好习惯吗?如果您将简单的lambda(不引用类方法)传递给此类构造函数,那么我理解没有错,但另一方面,它提供了将匿名内部类作为参数传递给 this 参考可能会暴露。
public class ClassA {
private ClassB classB;
public ClassA() {
// fine
classB = new ClassB(integer -> integer % 2 == 0);
// oops
classB = new ClassB(new Function<Integer, Boolean>() {
@Override
public Boolean apply(Integer integer) {
return integer % 2 == 0;
}
});
}
}
public class ClassB {
private final Function<Integer, Boolean> function;
public ClassB(Function<Integer, Boolean> function) {
this.function = function;
}
}
答案 0 :(得分:1)
设计在构造函数中接受
Runnable
,Function
,Predicate
作为参数的类是一种好习惯吗?
是,与其他任何对象一样。只要不公开this
引用,就可以将所需的任何内容传递给构造函数。
在您的示例中,ClassA
损坏了,而ClassB
是线程安全的。您正在通过在其构造函数中创建内部匿名类并将其传递给另一个对象来隐式地使this
引用脱离ClassA
(父对象)。但是具有ClassB
参数的类(Function
)是安全构造的。
答案 1 :(得分:0)
设计接受Runnable的类是一个好习惯吗
如果您查看java.lang.Thread
,则可以找到此类构造函数
public Thread(Runnable target) {}
答案是yes
,即使Oracle也这样做。