我有一个实现通用接口的通用类型。 Java编译器在所有情况下都能正确推断出类型的type参数中的约束,但无法一次推断出约束。
请参见下面的通用类中的getValue()
方法实现:
package test.gen.company;
public class GenericProblem {
Generic<ISpecific> gen = new Generic<>();
//compiler has no problems here
ISpecific val = gen.getValue();
Generic<IMoreSpecific> gen2 = new Generic<>();
//both of these are OK
ISpecific val1 = gen2.getValue();
IMoreSpecific val2 = gen2.getValue();
//compiler won't allow this,
//correctly complains irrelevant is not within bounds
//Generic<Irrelevant> gen;
}
interface IGeneric<T>{
T getValue();
void setValue(T in);
}
interface ISpecific {}
interface IMoreSpecific extends ISpecific {}
interface Irrelevant{}
class ISpecificImplementer implements ISpecific {}
class Generic<T extends ISpecific> implements IGeneric<T> {
@Override
public T getValue() {
//error: required T, found ISpecificImplementer
return new ISpecificImplementer();
//Unchecked cast
//return (T) new ISpecificImplementer();
}
@Override
public void setValue(T in) {
//no complaints here, compiler knows T is ISpecific
wantSomeB(in);
}
private void wantSomeB(ISpecific in){
if (in == null) {
throw new RuntimeException("I'm completely meaningless");
}
}
}
编译器基于setValue(T in)
的类型参数将T extends ISpecific
中的参数类型设置为Generic
,但是不能在{{1}中设置T
的类型}
当我在T getValue()
中对T
使用强制类型转换时,它会抱怨未检查的强制类型转换。
为什么类型推断对设置方法有用,但对getter不起作用?
答案 0 :(得分:3)
T
中的 Generic<T extends ISpecific>
可以扩展为ISpecific
的任何类型。
这意味着它可以为ISpecificImplementer
,或者它可以为其他匹配类型。 T
的选择不取决于决定方法。取决于创建Generic<T>
实例的情况。
在getValue()
内部,您试图返回一个ISpecificImplementer
。现在T
可能为ISpecificImplementer
,或者它可能是其他不兼容的类型。因此,它需要强制转换。强制转换为泛型类型会产生警告,因为它绕过了泛型打算提供的类型安全性。
假设SomeOtherType
是另一个实现ISpecific
的类。
如果实例化一个Generic<SomeOtherType>
并调用getValue()
,则将导致强制转换异常,因为getValue()
应该返回一个SomeOtherType
,但是它会实际上尝试返回一个ISpecificImplementer
。这就是为什么会有编译警告的原因。