2017-02-24 63 views
2

提供类型的变量值我有此类:对于另一个构造

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); 
} 

是否有任何方法可以让构造函数不包含某些类型变量来调用另一个类型变量wh ich呢?为什么这个限制?

编辑: 我的用例:我有一个类可选keyExtractor。键类型是类型参数之一。如果用户不提供keyExtractor,我只使用一个返回任何常量非空值。

+0

类型变量不属于构造函数。它属于类型(在实例上下文中)。 –

+0

编辑我的答案以修复术语。但为什么不编译? – Oliv

+0

我发现了一个解决办法:投将原始类型:'这((供应商)() - > TRUE);'。但为什么? – Oliv

回答

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没有方法,暴露了T型,所以没有点,为用户把它摆在首位:

public class Test { 
    public Test() { 
     this((Supplier)() -> true); 
    } 

    public Test(Supplier<?> c) { 
     this.c = c; 
    } 
} 
3

假设你写:

Test<String> t = new Test<>(); 

导致其他构造函数被调用;有效:

Test<String> t = new Test<String>(() -> true); 

但这不是键入正确的:() -> true不提供String,它提供了一个Boolean(或Serializable,或Object)。

如果你想提供一个默认的构造函数这样, 你需要返回,可强制转换为任何一个值:仅此值是null

this(() -> null); 

或者,删除默认的构造函数,并提供一个不带参数的工厂方法:

static Test<Boolean> createInstance() { 
    return new Test<>(() -> true); 
}