Jac*_*ith 9 java generics casting covariance
public void wahey(List<Object> list) {}
wahey(new LinkedList<Number>());
Run Code Online (Sandbox Code Playgroud)
对方法的调用不会进行类型检查.我甚至无法将参数强制转换如下:
wahey((List<Object>) new LinkedList<Number>());
Run Code Online (Sandbox Code Playgroud)
根据我的研究,我收集到不允许这样做的原因是类型安全.如果允许我们执行上述操作,那么我们可以执行以下操作:
List<Double> ld;
wahey(ld);
Run Code Online (Sandbox Code Playgroud)
在方法wahey中,我们可以在输入列表中添加一些字符串(因为参数维护List<Object>引用).现在,在方法调用之后,ld引用一个带有类型的列表List<Double>,但实际列表包含一些String对象!
这似乎与没有泛型的Java正常工作方式不同.例如:
Object o;
Double d;
String s;
o = s;
d = (Double) o;
Run Code Online (Sandbox Code Playgroud)
我们在这里做的基本上是相同的,除了这将通过编译时检查,并且只在运行时失败.带有列表的版本将无法编译.
这让我相信这纯粹是关于泛型类型限制的设计决策.我希望对这个决定有所评论?
Tyl*_*nry 11
你在"没有泛型"的例子中所做的是一个演员,它清楚表明你正在做一些类型不安全的事情.与泛型相当的是:
Object o;
List<Double> d;
String s;
o = s;
d.add((Double) o);
Run Code Online (Sandbox Code Playgroud)
其行为方式相同(编译,但在运行时失败).不允许您询问的行为的原因是因为它允许隐式类型不安全操作,这在代码中更难注意到.例如:
public void Foo(List<Object> list, Object obj) {
list.add(obj);
}
Run Code Online (Sandbox Code Playgroud)
这看起来非常好并且类型安全,直到你这样称呼:
List<Double> list_d;
String s;
Foo(list_d, s);
Run Code Online (Sandbox Code Playgroud)
这也看起来类型安全,因为你作为调用者并不一定知道Foo将如何处理它的参数.
因此,在这种情况下,您有两个看似类型安全的代码,这些代码最终都是类型不安全的.这很糟糕,因为它是隐藏的,因此难以避免并且难以调试.
考虑一下......
List<Integer> nums = new ArrayList<Integer>();
List<Object> objs = nums
objs.add("Oh no!");
int x = nums.get(0); //throws ClassCastException
Run Code Online (Sandbox Code Playgroud)
您可以将任何父类型的内容添加到列表中,这可能不是以前声明的内容,如上例所示,会导致各种问题.因此,不允许这样做.