列表与列表

为什么我们在使用List而不是在使用List时会丢失类型安全性? 他们基本上不一样吗?

编辑 :我发现以下给出了编译错误

 public class TestClass { static void func(List o, Object s){ o.add(s); } public static void main(String[] args){ func(new ArrayList(), new Integer(1)); } } 

而事实并非如此

 public class TestClass { static void func(List o, Object s){ o.add(s); } public static void main(String[] args){ func(new ArrayList(), new Integer(1)); } } 

为什么?

为什么我们在使用List而不是在使用List时会丢失类型安全性? 他们基本上不一样吗?

不,他们不是一回事。

如果您要提供API,

 class API { static List getList() { ... } static void modifyList(List l) { ... } } 

并且客户端使用它不正确

 List list = API.getList(); API.modifyList(list); for (Integer i : list) { ... } // Invalid 

然后,当您的API指定List它们会收到编译时错误,但是当API.getList()返回List并且API.modifyList(list)采用不带generics类型参数的List不会。

编辑:

在评论中你提到了改变

 void func(List s, Object c) { s.add(c); } 

 void func(List s, Object c) { s.add(c); } 

以便

 func(new List(), ""); 

会工作。

这违反了类型安全。 这种类型安全的方法是

  void func(List s, T c) { s.add(c); } 

这基本上是说func是一个参数化函数,它接受一个List它的类型可以是T的任何超类,类型为T,并将值添加到列表中。

List您不知道某种类型的列表。 它可以是ListList等。
它实际上等同于ListList List ,除了它没有记录这个事实。 它仅支持向后兼容性。

List对象列表任何类型的任何对象都可以放在其中,与List相反,例如,它只接受字符串。

所以不,他们不是一回事。

List实际上不比List更安全。 但是,代码中的Object确实意味着意图。 当其他人稍后查看它时,他们可以看到您故意选择Object作为类型,而不是想知道您是否忘记放置类型或存储其他内容并将其类型化为其他地方。

由于代码的读取次数超过了写入次数,因此稍后对代码意图的提示非常有价值。

使用List而不是List时有编译器警告的原因是当你有一个List ,编译器不知道它是什么类型的List,所以当你可以把它当作List ,编译器无法确保在代码中的某个其他位置未将其设置为引用List并且无法检查generics的类型安全性。 这实际上是编译器警告 – 它说无法确保generics的类型安全性,并且它也不会在运行时发生(直到稍后在代码中存在实际的强制转换)。

出于此目的,您可以说它们是相同的。 但据推测,你几乎从未真正用纯粹的Object实例填充List 。 他们是String或什么的。 在这个例子中, List在技​​术上使用generics,但并没有真正利用它。 因此,它失去了generics的编译时类型检查。