我有这堂课:
public class Test<T> {
public Test() {
this(() -> true); // error here
}
public Test(Supplier<T> c) {
}
}
编译因以下错误而失败:
Error:(23, 24) java: incompatible types: bad return type in lambda expression
boolean cannot be converted to T
我发现的唯一解决方法是使用静态工厂方法:
public static Test<Boolean> makeDefault() {
return new Test<>(() -> true);
}
对于不包含某些类型变量的构造函数,是否有任何方法可以调用另一个?为什么会出现这种限制?
修改
我的用例:我有一个带有可选keyExtractor
的类。键类型是类型参数之一。如果用户没有提供keyExtractor
,我只使用一个返回任何常量非空值。
答案 0 :(得分:3)
假设您要写:
Test<String> t = new Test<>();
这会导致调用其他构造函数;有效:
Test<String> t = new Test<String>(() -> true);
但这不是类型正确:() -> true
不提供String
,它提供Boolean
(或Serializable
或Object
)
如果你想提供这样的默认构造函数,
你需要返回一个可以强制转换为任何值的值:唯一的值是null
:
this(() -> null);
或者,删除默认构造函数,并提供no-arg工厂方法:
static Test<Boolean> createInstance() {
return new Test<>(() -> true);
}
答案 1 :(得分:1)
要使其编译,您可以执行转换为原始类型:
public class Test<T> {
public Test() {
this((Supplier) () -> true);
}
public Test(Supplier<T> c) {
this.c = c;
}
}
这有一个缺点,即如果用户在调用构造函数时提供了错误的类型参数,他可能会出现意外ClassCastException
:
Test<Integer> t = new Test<>();
System.out.println(t.supplier().get()); // prints "true"
更好的方法是使用静态工厂方法,它会向用户明确说明Supplier
类型:
public class Test<T> {
public static Test<Boolean> newWithConstantSupplier() {
return new Test<>(() -> true);
}
public Test(Supplier<T> c) {
this.c = c;
}
}
在我的情况下,我最终删除了T
参数,并取消Supplier<?>
,因为我在公共API中没有公开API的方法,因此有T
类型,因此有&#39}。用户无需首先使用它:
public class Test {
public Test() {
this((Supplier) () -> true);
}
public Test(Supplier<?> c) {
this.c = c;
}
}