泛型中的? 通配符以及泛型的边界

本文深入探讨了Java中泛型的基本概念及其使用方法,包括?通配符的应用场景、泛型的上边界和下边界的定义及注意事项。通过具体示例说明了如何在集合操作中正确运用泛型来提高代码的灵活性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

?通配符

当接收的类型不确定时,可以使用?通配符,?可以指向任何类型

public class Demo {
   public static void main(String[] args) {
    xx(new ArrayList<String>());
    xx(new ArrayList<Integer>());
}

   public static void xx(Collection<?> c){
       /*当使用?通配符时,不能再调用与类型相关的方法
    * 因为?指向的是一种不确定的类型
    */
       //c.add("sss");

       c.size();//这个方法与类型无关
       for(Object ob: c){
           System.out.println(ob);
       }
   }
}

泛型的上边界和下边界

1.限制上边界

正确使用方法:Vector<? extends Number> x=new Vector<Integer>();

错误使用方法:Vector<? extends Number> x=new Vector<String>();

泛型类中的使用方法:

//继承它的子类中的泛型必须实现Serializable和Cloneable接口
public class BaseDao<T extends Serializable,Cloneable> {
 }
 //例如
  public class BookDao extends BaseDao<Book> {

     }
  //这里的Book需要实现这两个接口
  public class Book implements Serializable,Cloneable{

  }

限制下边界

正确使用方法:Vector<? extends Integer> x=new Vector<Number>();

错误使用方法:Vector<? extends Integer> x=new Vector<Byte>();

注意:以下代码编译不能通过

     public void add(List<? extends Number> list){
      //当使用?通配符时,不能再调用与类型相关的方法,指定了边界也不行
       list.add(100);
   }
<think>嗯,用户之前问过Java集合框架的接口和类,现在又问集合,显然是想更深入了解集合框架的高级特性。我需要先回顾一下之前的回答,确保这次内容衔接自然。 首先,集合是Java中的一个重要概念,用来解决集合元素类安全的问题。在Java 5之前,集合可以存储任何Object类,取出时需要强制类转换,容易出错。的引入让集合在编译时就能检查类,避免运行时错误。 用户可能已经了解集合的基本结构,现在需要解释如何应用于这些集合。我应该从的基本概念讲起,说明为什么需要,然后具体到集合中的应用,比如ArrayList<String>这样的例子。 还要注意用户可能是初学者,需要用简单易懂的语言,避免过于技术化的术语。同时,可能需要对比非集合的问题,来突出的好处,比如类安全和避免强制转换。 另外,用户可能想知道如何使用集合,所以需要提供一些代码示例,比如声明、添加元素、遍历等。同时,也要提到类擦除,这是Java的一个特点,虽然编译时检查类,但运行时信息会被擦除,这可能引发一些注意事项。 可能还需要提到通配符边界的概念,比如<? extends T>和<? super T>,但不宜太深入,避免让用户感到困惑。重点还是放在集合的基本使用和优势上。 最后,总结集合的重要性,以及在实际开发中的最佳实践,比如总是使用来保证代码的健壮性。同时,可以对比旧版代码,说明带来的改进。</think>#### 一、集合的核心定义 **集合(Generic Collections)** 是Java 5引入的类安全机制,通过在集合框架中**显式声明元素类**,解决传统集合存在的**类不安全**和**强制类转换**问题。例如: ```java // 非集合(存在类不安全) List list = new ArrayList(); list.add("Hello"); Integer num = (Integer) list.get(0); // 运行时抛出ClassCastException // 集合(编译时类检查) List<String> genericList = new ArrayList<>(); genericList.add("Hello"); String str = genericList.get(0); // 无需强制转换,直接获取String类 ``` --- #### 二、集合的核心价值 1. **类安全(Type Safety)** - 编译器在**编译阶段**检查元素类,禁止插入不兼容类。 - 示例:`List<Integer>` 无法添加 `String` 类元素。 2. **消除强制类转换(No Casting)** - 从集合中获取元素时,直接返回声明类,无需显式转换。 3. **代码可读性提升** - 集合声明中明确元素类(如 `Map<String, Integer>`),增强代码自描述性。 --- #### 三、集合的语法结构 ##### 1. 类声明 集合框架的接口和类均通过**类参数**定义: ```java public interface List<E> { // E为类参数 boolean add(E element); E get(int index); } ``` ##### 2. 集合实例化 使用时需指定**具体类**(如 `String`、`Integer`): ```java List<String> names = new ArrayList<>(); // 菱形语法(Java 7+) Map<Integer, String> idToName = new HashMap<>(); ``` --- #### 四、集合的典应用 ##### 1. 与集合框架的结合 | 集合类 | 声明示例 | 特点 | |---------------------------|---------------------------------|-----------------------------------| | **`List<T>`** | `List<LocalDate>` | 存储特定类的对象列表 | | **`Set<T>`** | `Set<Double>` | 确保元素唯一性且类一致 | | **`Map<K,V>`** | `Map<String, Employee>` | 键值对类明确 | | **`Queue<T>`** | `Queue<File>` | 按类处理队列元素 | ##### 2. 遍历与操作 ```java List<Student> students = new ArrayList<>(); students.add(new Student("Alice", 90)); students.add(new Student("Bob", 85)); // 遍历时直接使用Student类 for (Student s : students) { System.out.println(s.getName()); } // 使用Lambda表达式处理集合 students.removeIf(s -> s.getScore() < 80); ``` --- #### 五、集合的进阶特性 ##### 1. **通配符(Wildcards)** - `<?>`:无界通配符(未知类,只读操作) ```java void printList(List<?> list) { for (Object elem : list) { /* 只能按Object处理 */ } } ``` - `<? extends T>`:上界通配符(接受T及其子类) ```java void processNumbers(List<? extends Number> list) { /* 可处理Integer、Double等 */ } ``` - `<? super T>`:下界通配符(接受T及其父类) ```java void addIntegers(List<? super Integer> list) { list.add(42); // 允许添加Integer或其父类的集合 } ``` ##### 2. **类擦除(Type Erasure)** - 仅在**编译阶段**有效,运行时类参数会被擦除(替换为`Object`或边界)。 - 示例:`List<String>` 和 `List<Integer>` 运行时均为 `List`。 --- #### 六、集合的注意事项 1. **不能使用基本类** - 参数必须是引用类,基本类需使用包装类: ```java List<Integer> scores = new ArrayList<>(); // 正确 List<int> scores = new ArrayList<>(); // 编译错误 ``` 2. **数组的限制** - 不能直接创建数组: ```java // List<String>[] arr = new List<String>[10]; // 编译错误 List<?>[] arr = new List<?>[10]; // 使用通配符绕过限制 ``` 3. **静态上下文中无法使用类参数** - 类的静态方法或变量无法引用参数: ```java class Box<T> { // static T data; // 编译错误 } ``` --- #### 七、集合 vs 非集合 | 特性 | 集合 | 非集合 | |---------------------|-----------------------------------|--------------------------------| | **类安全** | 编译时检查类 | 运行时可能抛出`ClassCastException` | | **代码可读性** | 声明中明确元素类 | 需通过注释或文档说明元素类 | | **强制类转换** | 无需显式转换 | 需手动转换(如 `(String) list.get(0)`) | | **兼容性** | Java 5+ | 所有Java版本 | --- #### 八、总结 集合通过**类参数化**解决了传统集合的类安全问题,是Java集合框架现代化的重要标志。开发者应始终优先使用集合,避免因类错误导致的运行时异常。结合**通配符**和**边界控制**,集合能灵活适应复杂的数据处理场景,同时保持代码的简洁与健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值