java 泛型 ??

param 的实际类型是 Pair<Interger> , 为什么不能赋值给 Number 呢 ?有朋友说,<? super Integer> 中的 ?可能是 Integer 可能是 Number 可能是 Object, 但是,传给 pairTest 的实际类型就是 Pair<Integer> 啊 ,不可能是其他类型( 比如 Pair<Object> )呀 ? 难道编译器没看到吗 ?

阅读 778
avatarAI BotBETA

在Java中,泛型是一种允许你在定义类、接口和方法时使用类型参数的功能。"Pair" 是一个泛型类,它接受两个类型参数,例如 <Integer, Number> 表示一个整数和一个数字的配对。

但是,你提到的情况有一个小错误。"Pair" 泛型的实际参数类型应该是 <Integer, Number>,而不是只有 <Integer>。这意味着它接受一个整数和一个数字作为参数,而不是只接受一个整数。

如果你尝试将一个 Pair<Integer, Number> 对象赋值给一个 Pair<Integer, Number> 变量,编译器会允许你这么做,因为它们的类型参数是一致的。然而,如果你尝试将一个 Pair<Integer, Number> 对象赋值给一个 Pair<Integer, Integer> 变量,编译器就会报错,因为虽然它们的类型参数都是 Integer,但是右侧的类型参数不一致。在这种情况下,你需要进行类型转换。

这是Java泛型的一个基本概念,即类型擦除。Java在编译时执行类型擦除,这意味着在运行时,泛型类型信息将被擦除,只留下原始类型信息。因此,你不能在运行时检查泛型参数的类型。这就是为什么你需要显式地进行类型转换的原因。

另外,注意 IntegerNumber 的子类,所以你可以将 Pair<Integer, Number> 对象赋值给 Pair<Integer, Number>Pair<Integer, Integer> 变量,因为 IntegerNumber 的子类。

3 个回答

? super Integer 可能是 Integer 可能是 Number 可能是 Object
不一定是 Number 所以不能直接赋值

楼上已经说的很明白了,你没有考虑到 传给 pairTest 的 pair<T> 这个T类型可以有很多(比如这个pair1),你怎么确保Number就能接收这个类型T呢?

 public static void main(String[] args) {
        Pair<Integer> pair = new Pair<>(100, 200);
        pairTest(pair);

        Pair<Object> pair1 = new Pair<>("first", "last");
        pairTest(pair1);
    }

    public static void pairTest(Pair<? super Integer> param) {
        Number number =  param.getFirst();
      
    }

其实如果你就非要Number类型,你还可以将泛型通配符改成继承Number,这样就不会报错:

 public static void pairTest(Pair<? extends Number> param) {
        Number number =  param.getFirst();
    }

即便你声明Pair对象的代码就在上面不远处,编译器也不会认为方法的传参都像你声明的Pair对象那样。ide会从声明一个方法的角度来看,这个方法的入参被你定义成Pair<? super Integer>,也就意味着只要入参Pair对象的泛型是Integer的任何父类,这个入参对象都是合理的。在Integer的所有父类中,至少有Object不是Number的实现。因此你的方法声明允许一个Pair<Object>对象传入,但是你在方法中却没有考虑处理这种情况,所以才会报错。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏