java泛型上下界

在这里插入图片描述
下面展示一些 内联代码片

public class Test_2 {
    public static void main(String[] args) {
        List<? extends B> list1 = new ArrayList<>();  // 上界
        List<? super B> list2 = new ArrayList<>();    // 下界
        A a = new A();
        B b = new B();
        C c = new C();
        Object o = new Object();
        // list1.add(o); 不能添加任何元素,因为List中具体是B的哪种子类无法确定
        // list1.add(a);
        // list1.add(b);
        // list1.add(c);
        o = list1.get(0);
        a = list1.get(0);
        b = list1.get(0);
        // c = list1.get(0); 编译错误,编译器无法向下转型
        // list2.add(o); 编译错误,
        // list2.add(a); 因为List中具体是B的哪种父类无法确定
        list2.add(b);
        list2.add(c);
        o = list2.get(0);
        // a = list2.get(0); 编译错误,因为List中具体是B的哪种父类无法确定,无法向下转型,而Object是所有类的父类
        // b = list2.get(0);
        // c = list2.get(0);
    }
}

class A {}

class B extends A {}

class C extends B {}

上界

1.上界用 extends关键字声明,表示参数化的类型可能是所指定的类或者其任意子类。例如<? extends B>,泛型的上界就是 B 类。
2.形如 List<? extends B>,具体哪一种不能确定,既可以是 B,也可以是 C。在尝试执行 add() 方法时,List中的类型不能确定是具体哪一种,所以会编译报错。在执行 get() 方法时,不管是 B 还是 C,都可以以 A 类对象来接收。所以 List<? extends B> 不能添加元素,具有只读属性,只能获取。

下界

1.下界用 super 关键字声明,表示参数化的类型可能是所指定的类型或者其任意父类。例如<? super B>,泛型的下界就是 B 类。
2.形如 List<? super B>,具体哪一种不能确定,既可以是 B,也可以是 A,直至 Object类。在尝试执行 add() 方法时,虽然 List 的具体类型不能确定,但是根据多态, B 类及其子类的对象肯定都可以被赋值给 B 的对象,所以只能添加 B 类及其子类的对象。在尝试执行 get() 方法时,List 中的类型是 B 类或者其父类的具体一种,向上直至 Object 类,所以只能将获取的元素赋值给 Object 对象。

### Java 上下界、通配符与类擦除的工作机制 #### 1. 上下界的原理及使用方法 在定义类或方法时,可以指定类参数的范围,即所谓的“上下界”。这使得开发者能够对传入的类施加约束。 - **上界(Upper Bound)** 使用 `extends` 关键字来设置的上限。例如,`<T extends Number>` 表示该只能接受继承自 `Number` 或其子类的对象。这种设计允许调用者传递特定类的对象并利用其特性[^2]。 ```java public class MyArray<E extends Number> { private E[] elements; public MyArray(int size) { this.elements = (E[]) new Number[size]; } public void addElement(E element) { for (int i = 0; i < elements.length; i++) { if (elements[i] == null) { elements[i] = element; break; } } } public double sum() { double total = 0; for (E e : elements) { if (e != null) { total += e.doubleValue(); } } return total; } } ``` - **下界(Lower Bound)** 下界通过 `super` 关键字设定,表示必须是某个具体类的父类或本身。例如 `<T super Integer>` 表示该可接收 `Integer` 及其超类的对象。然而需要注意的是,Java 中并没有真正的“下界”,因为只存在于编译期,运行时不保留此类信息[^3]。 #### 2. 通配符的作用及其工作机制 通配符是一种特殊的形式,用于表达不确定的具体类。它可以增强程序灵活性的同时维持安全性。 - **无界通配符 (`?`)** 这是最简单的通配符形式,代表任意未知类。当只需要操作不依赖于实际类的成员时非常有用[^5]。 ```java public static int countElements(List<?> list) { return list.size(); } ``` - **有界通配符** - 上界通配符:`<? extends T>` 指定所涉及的类为某给定类或者它的派生类。 ```java public static double calculateSum(List<? extends Number> numbers) { double result = 0; for(Number num : numbers){ result += num.doubleValue(); } return result; } ``` - 下界通配符:`<? super T>` 则相反,限定类为其基类之一。 ```java public static void copy(List<? extends Object> source, List<? super String> destination) { for(Object obj : source){ if(obj instanceof String){ destination.add((String)obj); } } } ``` #### 3. 类擦除的原理及影响 类擦除是指 JVM 在执行阶段不会区分不同的实例;所有的都被还原成原始类(Raw Type)。这一过程发生在编译期间,目的是为了兼容旧版本代码以及简化内存管理逻辑[^4]。 - 编译器负责验证所有基于的安全规则,并将最终产物转化为不含任何额外元数据的形式提交给解释器加载和运行。 - 结果就是像 `List<String>` 和 `List<Integer>` 实际上都变成了普通的 `List` 对象,在反射或其他动态场景下调用可能会引发意外错误。 ```java // 示例展示即使声明不同也共享同一Class实体 public class TestTypeErasure{ public static void main(String args[]){ List<String> strList=new ArrayList<>(); List<Integer> intList=new ArrayList<>(); System.out.println(strList.getClass()==intList.getClass());//true } } ``` #### 总结 综上所述,理解并掌握好这些概念对于写出高效且健壮的应用至关重要。合理运用能极大提升开发效率减少重复劳动量同时也增强了系统的鲁棒性和扩展能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值