Discuss / Java / 为什么只有只读权限?

为什么只有只读权限?

Topic source
int add(Pair<? extends Number> p) {}

p在经过泛型擦拭后变成:

Pair<Number> p

对p的操作都应该基于Number类型。

现在假设抽象类Number是可以实例化的,

假设传入add的实参是:

Pair<Number> p

与形参经过泛型擦拭后的类型相同,现在在add中调用:

 p.setFirst(new Number(2));

new Number(2) 既满足泛型擦拭后p的要求,也满足p实际类型的要求,为什么还是会报错?

代码如下:

public class Main {    public static void main(String[] args) {        Main main = new Main();        Pair<MyNumber> pair = new Pair<>(new MyNumber(0), new MyNumber(1));        main.func(pair);    }    public void func(Pair<? extends MyNumber> pair) {        System.out.println(pair.getFirst() + " " + pair.getLast()); // 0 1        pair.setFirst(new MyNumber(2)); // 报错    }}class MyNumber {    private int value;    public MyNumber(int value) {        this.value = value;    }    public MyNumber() {    }    @Override    public String toString() {        return "" + value;    }}class Pair<T> {    private T first;    private T last;    public Pair(T first, T last) {        this.first = first;        this.last = last;    }    public T getFirst() {        return first;    }    public T getLast() {        return last;    }    public void setFirst(T first) {        this.first = first;    }    public void setLast(T last) {        this.last = last;    }}

代码如下

public class Main {
    public static void main(String[] args) {
        Main main = new Main();

        Pair<MyNumber> pair = new Pair<>(new MyNumber(0), new MyNumber(1));
        main.func(pair);
    }

    public void func(Pair<? extends MyNumber> pair) {
        System.out.println(pair.getFirst() + " " + pair.getLast());
        pair.setFirst(new MyNumber(2)); // 报错
    }
}

class MyNumber {

    private int value;

    public MyNumber(int value) {
        this.value = value;
    }

    public MyNumber() {
    }

    @Override
    public String toString() {
        return "" + value;
    }
}

class Pair<T> {
    private T first;
    private T last;

    public Pair(T first, T last) {
        this.first = first;
        this.last = last;
    }

    public T getFirst() {
        return first;
    }

    public T getLast() {
        return last;
    }

    public void setFirst(T first) {
        this.first = first;
    }

    public void setLast(T last) {
        this.last = last;
    }
}

这个问题我也在思考,感觉还是和擦拭法有关,但不知道为什么

因为你这个编译器无法获取泛型的类型

extends 改成 super 就正常了

洪哥传奇

#6 Created at ... [Delete] [Delete and Lock User]

编译时,对于Main.func方法,因为<? extends MyNumber>无法确定参数的泛型类型(pair的泛型类型可能为MyNumber和其子类)。试想如果pair的泛型类型为MyNumber的子类时,pair.setFirst(new MyNumber(2))就是不行的。

若夜无魇

#7 Created at ... [Delete] [Delete and Lock User]

没明白. 这里的 <? extends MyNumber> 不是指定的MyNumber 及 MyNumber 的子类吗?为什么的pair的泛型类型为MyNumber的子类时, 反而 new MyNumber不可以?

廖雪峰

#8 Created at ... [Delete] [Delete and Lock User]

你的问题就问错了,不是有没有只读权限,而是写方法违反了类型安全原则,详细解释在下一节

花间的酒

#9 Created at ... [Delete] [Delete and Lock User]

因为 

Pair<? extends Number> p

不能确定p具体是什么

不能传入Number,因为p可能是 Pair<Integer> 

不能传入Integer,因为p可能是 Pair<Double>


  • 1

Reply