List、List<Object>、List<?>的区别

通过一个例子来比较这几种写法的区别

public class ListWithoutGeneric {
    public static void main(String[] args) {
        // 第一段:不使用泛型的方式
        List a1 = new ArrayList();
        a1.add(new Object());
        a1.add(new Integer(1));
        a1.add(new String("a1"));

        // 第二段:把a1赋值给List<Object>类型的a2,看似a2与a1没有区别
        List<Object> a2 = a1;
        a2.add(new Object());
        a2.add(new Integer(2));
        a2.add(new String("a2"));
        // 但是如果尝试把一个带有其它类型泛型的b2赋值给a2,则会编译报错
        List<String> b2 = new ArrayList<>();
        // 编译报错,这也是List与List<Object>的区别
        a2 = b2;

        // 第三段:把a1赋值给List<Integer>类型的a3,赋值过程没有编译报错,主要为了向前兼容(泛型jdk1.5之后才出现)
        List<Integer> a3 = a1;
        a3.add(new Integer(3));
        // java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.Integer
        Integer integer = a3.get(0);
        // 编译报错,不允许add非Integer类型
        a3.add(new Object());
        a3.add(new String("a3"));

        // 第四段:把a1赋值给List<?>类型的a4
        List<?> a4 = a1;
        a4.remove(0);
        a4.clear();
        a4.add(null);
        // 编译出错,不允许add非null的数据
        a4.add(new Object());
    }
}

 

1、第一段:定义了一个没使用泛型的List a1,向a1中添加不同类型的元素,所有功能都可以正常使用,但使用时会有类型强制转换异常的风险。

2、第二段:把a1赋值给List<Object>类型的a2,再往a2添加不同类型元素,不会编译报错,看似a2与a1没有区别,但是如果尝试把一个带有其它类型泛型(List<String>)的b2赋值给a2,则会编译报错,除非让泛型保持一致。

这也是List与List<Object>的区别:泛型之间只有同类型才能相互赋值。

3、第三段:把a1赋值给List<Integer>类型的a3,赋值过程没有编译报错,主要为了向前兼容(泛型jdk1.5之后才出现),但如果直接用Integer类型取值,会报类型转换异常。因为a3有了泛型约束,再添加其它类型元素,则会编译报错。

4、List<?>是通配符集合,一般作为参数来接收外部的集合,或者返回一个不知道具体元素类型的集合。它可以被任何类型的集合引用赋值,也可以删除元素。但是因为类型的不确定,所有不能添加非null元素(null属于任何类型)。

 

以上内容根据《码出高效Java开发手册》学习整理

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Java中,`List<List<Object>>` 是一种嵌套的泛型集合类型,表示一个包含多个列表的列表。每个内部列表都可以包含不同类型的对象。 下面是使用 `List<List<Object>>` 的基本语法: 1. 导入必要的类: ```java import java.util.List; import java.util.ArrayList; ``` 2. 声明和创建一个 `List<List<Object>>` 对象: ```java List<List<Object>> data = new ArrayList<>(); ``` 3. 向 `data` 添加内部列表: ```java List<Object> innerList1 = new ArrayList<>(); innerList1.add("John"); innerList1.add(25); innerList1.add("New York"); List<Object> innerList2 = new ArrayList<>(); innerList2.add("Alice"); innerList2.add(30); innerList2.add("London"); data.add(innerList1); data.add(innerList2); ``` 4. 访问和操作 `List<List<Object>>` 中的数据: ```java // 获取第一个内部列表 List<Object> firstInnerList = data.get(0); // 获取第一个内部列表的第一个元素 Object firstElement = firstInnerList.get(0); // 修改第二个内部列表的第二个元素 data.get(1).set(1, 31); // 遍历整个 `data` 列表 for (List<Object> innerList : data) { for (Object element : innerList) { System.out.print(element + " "); } System.out.println(); } ``` `List<List<Object>>` 可以灵活地存储和操作不同类型的数据。每个内部列表都可以根据需要进行添加、删除、修改和访问操作。注意,每个内部列表的长度可以不同,这使得 `List<List<Object>>` 更加灵活和适应各种数据结构的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@从入门到入土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值