我正在阅读Effective Java 3,并在第43项中注意到以下代码:"首选方法引用而不是lambdas":
TreeMap<K,V>::new
请注意类型参数。我总是做:
TreeMap::new
我使用 Intellij,但从未收到有关此警告或任何更改它的建议。实际上,当我让IDE将上述方法引用更改为lambda时,它会将其转换为
() -> new TreeMap<Integer, Integer>()
包含类型参数的价值是什么?编译器不能根据变量的类型参数推断出来吗?根据 IDE 如何将方法引用转换为 lambda,它似乎可以。
构造函数引用TreeMap::new
与使用 菱形类型推断 (§15.13.1) 相同:
为方便起见,当泛型类型的名称用于引用实例方法(其中接收器成为第一个参数)时,目标类型用于确定类型参数。这有利于用
Pair::first
代替Pair<String,Integer>::first
。同样,像
Pair::new
这样的方法引用被视为"菱形"实例创建(new Pair<>())
。由于"菱形"是隐式的,因此此窗体不会实例化原始类型;实际上,无法表示对原始类型的构造函数的引用。
您需要在或多或少与需要向构造函数显式提供类型参数时相同的情况下显式提供类型参数。
例如,在下文中,对get
的调用阻止在推理supplier
期间考虑返回分配,因此推断T
ArrayList<Object>
:
class Example {
public static void main(String[] args) {
ArrayList<String> list =
supplier(ArrayList::new).get(); // compile error
}
static <T> Supplier<T> supplier(Supplier<T> s) { return s; }
}
在那个人为的例子中,我们必须使用ArrayList<String>::new
.