java的“?”通配符

通配符

通配符解决的是:一个方法可以接收所有的泛型类型,但是又不能够让用户随意修改。

?通配符:作用于方法参数声明:

​​​​​​​public static void print(MyClass<?> myClass){
}

为什么 有通配符?

在类中追加了泛型的定义后,避免了ClassCastException的问题,但是又会产生新的情况:参数的统一问题

什么 意思???看一段代码解释:

这段代码用泛型定义了一个Message类,在主类里写了个方法打印Message创建的对象的message属性

class Message<T> {
    private T message;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }
}


public class 通配符 {
    public static void main(String[] args) {
        Message<String> message = new Message<>();
        message.setMessage("hello");
        method(message);
    }
    
    public static void method(Message<String> str){
        System.out.println(str);
    }
}

看上去没有问题,那么void main里new了一个Integer类型的message怎么办?调用method方法就会报错

public class 通配符 {
    public static void main(String[] args) {
        Message<Integer> message = new Message<>();
        message.setMessage(123);
        method(message);//这里就会报错
    }

    public static void method(Message<String> str){
        System.out.println(str);
    }
}

那么改一下,使用通配符就可以解决问题

public class 通配符 {
    public static void main(String[] args) {
        Message<Integer> message = new Message<>();
        message.setMessage(123);
        method(message);
    }

    public static void method(Message<?> str){
        System.out.println(str);
    }
}

此时方法参数表示可以接受任意类型的Message对象。


使用通配符之后无法设置值

由于无法确定入参的类型,因此“?”通配符下的泛型参数,只能取得类中的属性值,无法进行属性值的设置。

public class 通配符 {
    public static void main(String[] args) {
        Message<Integer> message = new Message<>();
        message.setMessage(123);
        method(message);
    }

    public static void method(Message<?> str){
        str.setMessage("232");//由于不知道str的具体类型,所以不能修改,会报错
        System.out.println(str);
    }
}

无法设置值的解决方案——上下限概念

在"?"的基础上又产生了两个子通配符:
? extends class:设置泛型上限:
例如:? extends Number,表示只能够设置Number或其子类,例如:Integer、Double等;
? super class:设置泛型下限:
例如:? super String,表示只能够设置String及其父类Object。

设置泛型上限——可以用于泛型类的声明,也可用于方法参数。

泛型类上限声明:(T必须是Number类的子类)

//设置上限
class Message<T extends Number>  {
    private T message;

    public T getMessage() {
        return message;
    }

    public void setMessage(T message) {
        this.message = message;
    }
}

方法参数声明上限:表示方法入参只能接受Num以及他的子类对象。

public static void method(Message<? extends Number> str){
    str.setMessage("232");//此时仍然无法确定str的具体类型,所以不能修改,会报错
    System.out.println(str);
}

方法参数设置泛型上限仍然只能取得类中属性值,而无法设置,因为父类的值子类不一定能使用(父类不一定能发生向下转型变为子类)。

设置泛型下限——只能用于方法参数

下限声明:? Super 类(>=类):都表示方法入参只能接受类及其父类对象

    public static void method(Message<? super Integer> str){
        str.setMessage(256);//现在可以设置了,因为子类可以天然向上转型
        System.out.println(str);
    }

方法参数设置泛型下限不仅可以取得类中属性值,还可以设置属性值。因为子类可以天然向上转型变成父类。

猜你喜欢

转载自blog.csdn.net/likunkun__/article/details/83820469