Java 泛型通配符上限和通配符下限(正在整理)

https://www.jianshu.com/p/66bd729bc129

<? extends T>上限通配,表示?是T的一个未知子类。
<? super T>下限通配,表示?是T的一个未知父类。

下面来分别讲一下

1. <? extends T> 上限通配

这里?表示一个未知的类,而T是一个具体的类,在实际使用的时候T需要替换成一个具体的类,表示实例化的时候泛型参数要是T的子类。

举个例子
我们有一个水果类

/**
 * 水果类
 */
public abstract class Fruit {
    public abstract void eat();
}

然后创建两种水果继承水果类Fruit

/**
 * 苹果类
 */
public class Apple extends Fruit {
    @Override
    public void eat() {
        System.out.println("我是苹果,我是酸酸甜甜的");
    }
}
/**
 * 香蕉类
 */
public class Banana extends Fruit {
    @Override
    public void eat() {
        System.out.println("我是香蕉,我是软软的");
    }
}

我们还需要一个吃瓜群众

/**
 * 吃瓜群众
 */
public class People<T extends  Fruit> {

    public void eatFruit(T t){
        t.eat();
    }
}

请注意定义People类的时候我们使用了泛型上限表示<T extends Fruit>
我们创建一个类测试一下

public class Test {
    public static void main(String[] args) {
        People<Apple> p1 = new People<>();
        p1.eatFruit(new Apple());

        People<Banana> p2 = new People<>();
        p2.eatFruit(new Banana());
    }
}

输出结果.png

若此时我们创建一个橙子类,但不继承自Fruit父类

/**
 * 橙子类
 */
public class Orange {
    public void eat() {
        System.out.println("我是橙子,我是酸酸的");
    }
}

编译时期就会报错,提示Orange不在范围内,应该要继承Fruit类

编译报错.png

2. <? super T> 下限通配

这里?表示一个未知的类,而T是一个具体的类,在实际使用的时候T需要替换成一个具体的类,表示实例化的时候泛型参数要是T的父类。

例如

public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
}

这里表示我们调用这个方法时可以传入参数是Integer或者Integer的父类,例如:

public class TestLowerBounded {
    public static void addNumbers(List<? super Integer> list) {
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }
    }

    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>();
        addNumbers(list1);

        List<Number> list2 = new ArrayList<>();
        addNumbers(list2);

        List<Object> list3 = new ArrayList<>();
        addNumbers(list3);

        List<String> list4 = new ArrayList<>();
        //编译错误,因为String不是Integer的父类
        //addNumbers(list4);
    }
}

Number和Object都是Integer的父类,所以编译通过,而String不是Integer的父类,编译报错。



以上就是泛型上限通配符和下限通配符的作用了,知识点比较小,希望可以一点一点积累,和大家一起进步。

原文地址:https://www.cnblogs.com/baxianhua/p/9204666.html

时间: 2024-12-13 13:01:33

Java 泛型通配符上限和通配符下限(正在整理)的相关文章

JAVA泛型之&lt;? extends T&gt;:(通配符上限)和&lt;? super T&gt;(通配符下限)

一.通配符上限和通配符下限接受的类型 通配符上限:<? extends T> 通配符下限:<? super T> 以下代码是测试结果,注释为解释说明 1 package xayd.hjj; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 class A{} 7 class B extends A implements F{} 8 class C extends A{} 9 class D extends A{

Java泛型解析(02):通配符限定

Java泛型解析(02):通配符限定 考虑一个这样的场景,计算数组中的最大元素. [code01] public class ArrayUtil { public static <T> T max(T[] array) { if (array == null || 0 == array.length) { return null ;} T max = array[0]; for (int i = 1; i < array.length; i++) { if (max.compareTo(

java 泛型的上限与下限

设置泛型对象的上限使用extends,表示参数类型只能是该类型或该类型的子类: 声明对象:类名<? extends 类> 对象名 定义类:类名<泛型标签 extends 类>{} 设置泛型对象的下限使用super,表示参数类型只能是该类型或该类型的父类: 声明对象:类名<? super 类> 对象名称 定义类:类名<泛型标签 extends类>{} public static void  show(List<? extends Number> l

我所认识的java泛型(主要讨论通配符的使用)

在使用java泛型的时候,经常会遇到类似的声明<?extends XXX>或者<? super XXX>,XXX代表一个类或接口.这到底是什么意思呢?今天看了些书有了一点儿体会,不知恰当与否,忘讨论之. 首先需要清楚一个事实,在java中上转型是安全的,下转型是不安全的.例如:String类是Object类的子类,我们可以将String强转为Object但是却不能将Object类强转为一个String,这很明显,因为在String类中包含了Object类没有的方法: 再来看一个事实

Java泛型学习笔记 - (七)浅析泛型中通配符的使用

一.基本概念:在学习Java泛型的过程中, 通配符是较难理解的一部分. 主要有以下三类:1. 无边界的通配符(Unbounded Wildcards), 就是<?>, 比如List<?>. 无边界的通配符的主要作用就是让泛型能够接受未知类型的数据. 2. 固定上边界的通配符(Upper Bounded Wildcards): 使用固定上边界的通配符的泛型, 就能够接受指定类及其子类类型的数据. 要声明使用该类通配符, 采用<? extends E>的形式, 这里的E就是

Java泛型解析(04):约束和局限性

Java泛型解析(04):约束和局限性 前两节,认识和学习了泛型的限定以及通配符,初学者可能需要一些时间去体会到泛型程序设计的好处和力量,特别是想成为库程序员的同学就需要下去体会通配符的运用了,应用程序员则需要掌握怎么使用泛型,这里针对泛型的使用中的约束和局限性做一个介绍性的讲解. 不能用基本类型实例化类型参数 这个很好理解,实例化泛型类时泛型参数不能使用基本类型,如List<int>这是不合法的,要存储基本类型则可以利用基本类型的包装类如List<Integer> .List&l

Java泛型解析(03):虚拟机执行泛型代码

Java泛型解析(03):虚拟机执行泛型代码 Java虚拟机是不存在泛型类型对象的,所有的对象都属于普通类,甚至在泛型实现的早起版本中,可以将使用泛型的程序编译为在1.0虚拟机上能够运行的class文件,这个向后兼容性后期被抛弃了,所以后来如果用Sun公司的编译器编译的泛型代码,是不能运行在Java5.0之前的虚拟机的,这样就导致了一些实际生产的问题,如一些遗留代码如何跟新的系统进行衔接,要弄明白这个问题,需要先了解一下虚拟机是怎么执行泛型代码的. 虚拟机的一种机制:擦除类型参数,并将其替换成特

泛型-通配符,受限泛型(上限和下限)

掌握通配符“?”的使用. 掌握受限泛型的设置. 掌握泛型与子类继承的限制. 具体内容 1.1匹配任意类型的通配符 在开发中对象的引用传递(向上向下传递)是最常见的,但是,在泛型的操作中,在进行引用传递的时候泛型类型必须匹配才可以传递,否则不能传递. 例如,如下没有进行泛型类型匹配,一个是String,一个是Object类型. package Thread1; class Info<T>{ private T var ; // 定义泛型变量 public void setVar(T var){

java泛型---通配符,泛型嵌套

package generic; import java.util.ArrayList; import java.util.List; /** * ? -->通配符,类型不确定,用于声明 变量|形参 上 * 不能用在: * 1,创建对象 * 2,创建泛型类 .泛型方法.泛型接口上 * */ public class WildcardTest { public static void main(String[] args) { //声明 List<?> list = new ArrayLi