尽管有很好的答案,但感谢@JB Nizet,我看到了声明是错误的案例,并且由于他没有冒险将其改编为答案,我将在这里用这个测试用例进行总结:
public class NumVal<C extends Number> {
Integer nextFibboInt (int secondLast,int last){ return sum(secondLast,last);};
C nextFibboC (C secondLast, C last){ return sum(secondLast,last);};
List<Integer> next2FibbosInt(int secondLast,int last){ return Arrays.asList(sum(secondLast,last), sum(sum(secondLast,last),last));};
List<C> next2FibbosC (C secondLast, C last){ return Arrays.asList(sum(secondLast,last), sum(sum(secondLast,last),last));};
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void main (String[] args){
Integer singleGenericSubtype = new NumVal<Integer>().nextFibboC(1,2); //This is the exclusive obvious for generics
Integer listGenericSubtype = new NumVal<Integer>().next2FibbosC(1,2).get(0); //This is the exclusive obvious for generics
Number singleGenericSuper = new NumVal<Number> ().nextFibboC(1,2);
Integer singleHardcodedTyped = new NumVal<Integer>().nextFibboInt(1,2);
Number listGenericSuper = new NumVal<Number> ().next2FibbosC(1,2).get(0);
Integer listTyped = new NumVal<Integer>().next2FibbosInt(1,2).get(0);
Number singleGenericSuperRaw = new NumVal().nextFibboC(1,2); // OK - These are the cases I was assuming as equivalent
Integer singleHardcodedTypedRaw = new NumVal().nextFibboInt(1,2); // OK - These are the cases I was assuming as equivalent
Number listGenericSuperRaw = new NumVal().next2FibbosC(1,2).get(0); // KO - These are the cases that I did not considerate that fail the hypothesis
Integer listHardcodedTypedRaw = new NumVal().next2FibbosInt(1,2).get(0); // KO - These are the cases that I did not considerate that fail the hypothesis
}
private <T extends Number> T sum(T o1, T o2) {
Number sum = new BigDecimal(o1.toString()).add(new BigDecimal(o2.toString()));
Object result = -1;
try { result = o1.getClass().getMethod("valueOf",String.class).invoke(null, sum.toString()); } catch (Exception e){}
return (T) result;
}
}
- 所以最后 2 个案例失败(在编译时),这意味着擦除的 raw 不能与 super 互换
<Number>
。使类原始似乎会删除该类的任何类型的任何方法签名(感谢@JB Nizet)
- 第一个失败是因为即使 C 在单独时被正确擦除为 Number,
List<C>
否则也会被擦除为List<Object>
- 第二次失败甚至更奇怪,因为令人惊讶的是我的原始类正在擦除
List<Integer>
硬编码返回方法的类型,即使它们没有以任何方式使用/与类 C 类型相关