了解java中的通配符“?“

目录

通配符的作用

先看一段代码

用通配符"?"后,代码变化

结论

通配符上界

通配符下界

对通配符上下界的注释理解及其练习代码


简记: ? 用于在泛型的使用,即为通配符.
在Java中,通配符(wildcard)主要用于泛型编程,用于表示一个不确定的类型。
通配符有三种形式:1.通配符<?> 2.通配符<? extends T> 3. 通配符<? super T>

通配符的作用

先看一段代码

java 复制代码
class Test0 {
    public static void main(String[] args) {
        System.out.println("===========1.String==============");
        Message<String> message1 = new Message<>();
        message1.setMessage("fly in the sky!");
        fun1(message1);

        System.out.println("===========2.Integer=============");
        Message<Integer> message2 = new Message<>();
        message2.setMessage(99);
        fun2(message2);

        System.out.println("===========3.Character============");
        Message<Character> message3 = new Message<>();
        message3.setMessage('s');
        func3(message3);

        System.out.println("===========4.Short================");
        Message<Short> message4 = new Message<>();
        message4.setMessage((short) 213);
        func4(message4);

        System.out.println("===========5.Long=================");
        Message<Long> message5 = new Message<>();
        message5.setMessage(1024L);
        func5(message5);

        System.out.println("===========6.Float=================");
        Message<Float> message6 = new Message<>();
        message6.setMessage(3.1415926f);
        func6(message6);

        System.out.println("===========7.Double================");
        Message<Double> message7 = new Message<>();
        message7.setMessage(1024.0213);
        func7(message7);

        System.out.println("===========8.Boolean===============");
        Message<Boolean> message8 = new Message<>();
        message8.setMessage(true);
        func8(message8);
    }

    public static void fun1(Message<String> tmp) {
        System.out.println(tmp.getMessage());

    }

    public static void fun2(Message<Integer> tmp) {
        System.out.println(tmp.getMessage());

    }

    public static void func3(Message<Character> tmp) {

        System.out.println(tmp.getMessage());

    }

    public static void func4(Message<Short> tmp) {
        System.out.println(tmp.getMessage());
    }

    public static void func5(Message<Long> tmp) {
        System.out.println(tmp.getMessage());
    }

    public static void func6(Message<Float> tmp) {
        System.out.println(tmp.getMessage());
    }

    public static void func7(Message<Double> tmp) {
        System.out.println(tmp.getMessage());
    }

    public static void func8(Message<Boolean> tmp) {
        System.out.println(tmp.getMessage());

    }
}

用通配符"?"后,代码变化

java 复制代码
class Test1 {
    public static void func(Message<?> temp) {
        System.out.println(temp.getMessage());
    }
    public static void main(String[] args) {
        System.out.println("===========1.String==============");
        Message<String> message1 = new Message<>();
        message1.setMessage("fly in the sky!");
        func(message1);

        System.out.println("===========2.Integer=============");
        Message<Integer> message2 = new Message<>();
        message2.setMessage(99);
        func(message2);

        System.out.println("===========3.Character============");
        Message<Character> message3 = new Message<>();
        message3.setMessage('s');
        func(message3);

        System.out.println("===========4.Short================");
        Message<Short> message4 = new Message<>();
        message4.setMessage((short) 213);
        func(message4);

        System.out.println("===========5.Long=================");
        Message<Long> message5 = new Message<>();
        message5.setMessage(1024L);
        func(message5);

        System.out.println("===========6.Float=================");
        Message<Float> message6 = new Message<>();
        message6.setMessage(3.1415926f);
        func(message6);

        System.out.println("===========7.Double================");
        Message<Double> message7 = new Message<>();
        message7.setMessage(1024.0213);
        func(message7);

        System.out.println("===========8.Boolean===============");
        Message<Boolean> message8 = new Message<>();
        message8.setMessage(true);
        func(message8);
    }
}

结论

结论:使用通配符"?"可以接收所有的泛型类型,从而大大减少代码量,


注:虽然通配符 "?" 可以接受任意类型,但正因为如此,由于不确定类型,所以在func方法中无法修改操作


在"?"的基础上又产生了两个子通配符:
? extends 类:设置通配符上限 => 通配符上界
? super 类:设置通配符下限 => 通配符下界

通配符上界

通配符上界
语法:
++<? extends 上界>
<? extends String>++//可以传入的实参类型是String或者String的子类

通配符的上界,不能进行写入数据,只能进行读取数据

通配符下界

通配符下界
语法:
++<? super 下界>++
++<? super Integer>++//代表 可以传入的实参的类型是 Integer或者 Integer的父类类型

通配符的下界,不能进行读取数据,只能写入数据

java 复制代码
class Food {
}

class Fruit extends Food {
}

class Apple extends Fruit {
}

class Banana extends Fruit {
}

对通配符上下界的注释理解及其练习代码

java 复制代码
class Food {}
class Fruit extends Food {}
class Apple extends Fruit {}
class Banana extends Fruit {}
class Plate<T> {//设置泛型
    private T message;
    public T getMessage() {
        return message;
    }
    public void setMessage(T message) {
        this.message = message;
    }
}
public class Test2 {
    public static void main1(String[] args) {
        Plate<Apple> applePlate = new Plate<>();
        applePlate.setMessage(new Apple());
        func1(applePlate);
        Plate<Banana> bananaPlate = new Plate<>();
        bananaPlate.setMessage(new Banana());
        func1(bananaPlate);
    }

    //通配符的上界
    //通配符的上界,不能进行写入数据,只能进行读取数据
    public static void func1(Plate<? extends Fruit> tmp) {
        //这里仍然不可以进行修改!tmp接收的是Fruit和他的子类,此时存储的元素应该是哪个子类无法确定。
        System.out.println(tmp.getMessage());
        Fruit b = tmp.getMessage();//向上转型
        System.out.println(b);
    }


    //通配符的下界
    //通配符的下界,不能进行读取数据,只能写入数据
    public static void main(String[] args) {
        Plate<Fruit> fruitPlate = new Plate<>();
        fruitPlate.setMessage(new Fruit());
        func2(fruitPlate);
        Plate<Food> foodPlate = new Plate<>();
        foodPlate.setMessage(new Food());
        func2(foodPlate);
    }

    public static void func2(Plate<? super Fruit> tmp) {
        //传入参数为Fruit及其父类 ,
        //此时可以修改!!添加的是Fruit 或者Fruit的子类
        tmp.setMessage(new Apple());
        tmp.setMessage(new Fruit());
        //不能接收,这里无法确定是哪个父类,父类太多了
    }
}
相关推荐
程序员-珍13 分钟前
使用openapi生成前端请求文件报错 ‘Token “Integer“ does not exist.‘
java·前端·spring boot·后端·restful·个人开发
弱冠少年20 分钟前
websockets库使用(基于Python)
开发语言·python·numpy
长天一色21 分钟前
C语言日志类库 zlog 使用指南(第五章 配置文件)
c语言·开发语言
一般清意味……33 分钟前
快速上手C语言【上】(非常详细!!!)
c语言·开发语言
卑微求AC33 分钟前
(C语言贪吃蛇)16.贪吃蛇食物位置随机(完结撒花)
linux·c语言·开发语言·嵌入式·c语言贪吃蛇
2401_8572979139 分钟前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
技术无疆43 分钟前
【Python】Streamlit:为数据科学与机器学习打造的简易应用框架
开发语言·人工智能·python·深度学习·神经网络·机器学习·数据挖掘
福大大架构师每日一题1 小时前
23.1 k8s监控中标签relabel的应用和原理
java·容器·kubernetes
金灰1 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5
菜鸟一皓1 小时前
IDEA的lombok插件不生效了?!!
java·ide·intellij-idea