📜  Java中的通配符(1)

📅  最后修改于: 2023-12-03 15:32:02.330000             🧑  作者: Mango

Java中的通配符

Java中的通配符是指在泛型中使用的符号'?'。与我们使用的'*'类似,它可以代表任何类型。本文将对Java中的通配符进行详细介绍。

通配符的作用

通配符可以用来限制泛型类型的范围。它可以代表任何类型,但并不意味着泛型可以接受任何类型。

例如,我们定义一个泛型类Box

public class Box<T> {
    private T item;

    public T getItem() {
        return item;
    }
    
    public void setItem(T item) {
        this.item = item;
    }
}

这个类可以接受任何类型的对象。我们可以定义一个Box对象来存储整数:

Box<Integer> intBox = new Box<>();
intBox.setItem(5);
Integer item = intBox.getItem();

但如果我们想要定义一个Box对象来存储任何类型的对象,该怎么办呢?这时候就需要使用通配符了:

Box<?> anyBox = new Box<>();

这里的'?'就是通配符,它可以代表任何类型。但是,由于我们不知道Box存储的是什么类型的对象,所以我们只能使用一些基本方法,例如getItem()setItem()

通配符的限制

虽然通配符可以代表任何类型,但它并不能接受任何类型。

例如:

Box<?> anyBox = new Box<>();
anyBox.setItem(5); // 编译错误,setItem()方法无法接受类型为int的参数

这是因为通配符会使泛型类型丢失,Java编译器并不知道要将'?'替换成什么类型。为了避免这种情况,可以使用有限制的通配符。

有限制的通配符

有限制的通配符使用extends关键字来设置限制,表示通配符可以接受限制范围内的子类。

例如:

public class Animal {...}
public class Cat extends Animal {...}

Box<? extends Animal> animalBox = new Box<>();
animalBox.setItem(new Animal()); // 编译错误,setItem()方法无法接受类型为Animal的参数
animalBox.setItem(new Cat()); // 正确,setItem()方法接受类型为Cat的子类参数

这里的通配符表示Box对象可以接受继承自Animal的子类。

通配符的束缚

通配符的限制不仅适用于参数类型,还适用于返回类型。这意味着带通配符的方法也必须受到限制,返回类型必须是通配符的上限。

例如:

public class Box<T> {
    private T item;

    public void setItem(T item) {
        this.item = item;
    }

    public T getItem() {
        return item;
    }

    public Box<?> boxCopy() {
        Box<?> copyBox = new Box<?>();
        copyBox.setItem(this.getItem());
        return copyBox;
    }
}

这里的boxCopy()方法返回一个新的Box对象,它的类型和原来的Box对象相同。由于Box对象的类型可能是任何类型,因此我们必须使用带通配符的泛型类型来定义它。但是,由于通配符不能接受任何类型,所以我们必须使用通配符的上限来定义返回类型,否则会发生编译错误。

总结

Java中的通配符可以用来限制泛型类型的范围。它可以代表任何类型,但并不意味着泛型可以接受任何类型。有限制的通配符使用extends关键字来设置限制,表示通配符可以接受限制范围内的子类。通配符的限制不仅适用于参数类型,还适用于返回类型。带通配符的泛型类型必须使用通配符的上限来定义返回类型。