列表与列表<对象>

2022-09-04 02:55:59

为什么我们在使用时会失去类型安全性,而在使用时却不会丢失类型安全性?它们基本上不是一回事吗?ListList<Object>

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

public class TestClass
{
    static void func(List<Object> o, Object s){
        o.add(s);
    }

    public static void main(String[] args){
        func(new ArrayList<String>(), 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<String>(), new Integer(1));
    }
}

为什么?


答案 1

List您不知道的某种类型的列表。它可以是 、 等。
它实际上等同于 、 或 ,除了它没有记录该事实。仅支持向后兼容性。List<String>List<Integer>List<?>List<? extends Object>

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

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


答案 2

为什么我们在使用时会失去类型安全性,而在使用时却不会丢失类型安全性?它们基本上不是一回事吗?ListList<Object>

不,它们不是一回事。

如果您要提供 API,

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

并且客户端不正确地使用它

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

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

编辑:

在评论中,您提到更改

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

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

因此

func(new List<String>(), "");

会工作。

这违反了类型安全。执行此操作的类型安全方法是

<T> void func(List<? super T> s, T c) { s.add(c); }

这基本上是说,这是一个参数化函数,它采用一个其类型可以是T的任何超类,以及一个类型T的值,并将该值添加到列表中。funcList


推荐