param 的实际类型是 Pair<Interger> , 为什么不能赋值给 Number 呢 ?有朋友说,<? super Integer> 中的 ?可能是 Integer 可能是 Number 可能是 Object, 但是,传给 pairTest 的实际类型就是 Pair<Integer> 啊 ,不可能是其他类型( 比如 Pair<Object> )呀 ? 难道编译器没看到吗 ?
param 的实际类型是 Pair<Interger> , 为什么不能赋值给 Number 呢 ?有朋友说,<? super Integer> 中的 ?可能是 Integer 可能是 Number 可能是 Object, 但是,传给 pairTest 的实际类型就是 Pair<Integer> 啊 ,不可能是其他类型( 比如 Pair<Object> )呀 ? 难道编译器没看到吗 ?
在Java中,泛型是一种允许你在定义类、接口和方法时使用类型参数的功能。"Pair" 是一个泛型类,它接受两个类型参数,例如 <Integer, Number>
表示一个整数和一个数字的配对。
但是,你提到的情况有一个小错误。"Pair" 泛型的实际参数类型应该是 <Integer, Number>
,而不是只有 <Integer>
。这意味着它接受一个整数和一个数字作为参数,而不是只接受一个整数。
如果你尝试将一个 Pair<Integer, Number>
对象赋值给一个 Pair<Integer, Number>
变量,编译器会允许你这么做,因为它们的类型参数是一致的。然而,如果你尝试将一个 Pair<Integer, Number>
对象赋值给一个 Pair<Integer, Integer>
变量,编译器就会报错,因为虽然它们的类型参数都是 Integer
,但是右侧的类型参数不一致。在这种情况下,你需要进行类型转换。
这是Java泛型的一个基本概念,即类型擦除。Java在编译时执行类型擦除,这意味着在运行时,泛型类型信息将被擦除,只留下原始类型信息。因此,你不能在运行时检查泛型参数的类型。这就是为什么你需要显式地进行类型转换的原因。
另外,注意 Integer
是 Number
的子类,所以你可以将 Pair<Integer, Number>
对象赋值给 Pair<Integer, Number>
或 Pair<Integer, Integer>
变量,因为 Integer
是 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>对象传入,但是你在方法中却没有考虑处理这种情况,所以才会报错。
15 回答6.8k 阅读
2 回答3.3k 阅读✓ 已解决
3 回答7k 阅读✓ 已解决
5 回答4.7k 阅读
3 回答5.1k 阅读
4 回答2.3k 阅读
2 回答2.3k 阅读✓ 已解决
? super Integer
可能是Integer
可能是Number
可能是Object
不一定是
Number
所以不能直接赋值