java - 为什么 Integer 的泛型在打印时没有分配 String 的值发出错误?
问题描述
这个问题也可以看成:为什么一个泛型的 String 赋值为 Integer 在打印时会发出运行时错误?但是这个问题的答案似乎很明显,标题问题对我来说不是。我不明白为什么一个错误而不是另一个错误。这个问题适用于这个例子。假设您有一个参数化的 Box 类:
class Box <T> {
T value;
void setValue(T value) {
this.value = value;
}
T getValue() {
return value;
}
}
你有这个类的三个实例,一个没有类型参数,另外两个有字符串或整数。String 和 Integer 的 Box 被实例化为原始对象:
Box rawBox = new Box();
Box <Integer> intBox = rawBox;
Box <String> stringBox = rawBox;
当我们通过原始引用传递 setValue() 值并通过相应的参数化引用打印 getValue() 时,我遇到的问题出现了:
Integer integerVal = 4;
rawBox.setValue(integerVal);
System.out.println(intBox.getValue());
// System.out.println(stringBox.getValue()); // ClassCastException a Integer cannot be assigned to a String
rawBox.setValue("hi");
System.out.println(intBox.getValue()); // Why is there no ClassCastException for assigning a String to Integer?
System.out.println(stringBox.getValue());
ClassCastException 错误仅在打印 getValue() 时发出,而不是在调用 setValue() 时发出。那么为什么具有 Integer 类型参数的参数化对象实例化为 rawtype 可以通过原始引用为其泛型分配 String 值,并且在打印 getValue() 时没有运行时错误,但如果相同的参数化类型有String 的类型参数和它的泛型通过原始类型分配了 Integer 的值,它会在打印 getValue() 时抛出 ClassCastException?
解决方案
您可能明白这Box.value
是Object
在运行时,因此Box.getValue
必须返回Object
。
PrintStream.println
对于所有基本类型、 forObject
和 for都有重载String
。Object.toString
这大概是为了避免在打印的值已知为 a 时额外调用String
。
所以想象一下生成的字节码对于这两个调用会是什么样子println
:
Integer integerVal = 4;
rawBox.setValue(integerVal);
System.out.println(intBox.getValue());
在这种情况下,intBox.getValue()
返回Object
,因此我们将调用println
接受的版本Object
。编译器知道返回值应该是Integer
,但这没关系,因为println
接受没有重载Integer
。
System.out.println(stringBox.getValue());
在这里,虽然stringBox.getValue()
返回Object
,编译器知道它应该是 aString
并且想要调用println
接受 a的版本String
。这需要将返回值向下转换为String
,这会失败,因为它实际上是一个Integer
.
推荐阅读
- python - Healpy 可以计算双谱来研究 CMB 地图的非高斯性吗?
- python - 如何在 a1D NumPy 数组的开头和结尾查找顺序 NaN 的索引?
- android - 我无法解析应用程序中 JSON 的嵌套类中的 mag 以及地点和时间,它们都将值显示为 null
- c++ - 我收到错误,例如 [Error] cannot convert '__complex__ int' to 'int' in assignment
- html - CSS中的超链接颜色样式
- python-3.x - 我的布尔标志没有在它应该触发的时候触发
- javascript - html2pdf 比原来的 HTML 增加了所有元素的大小
- ios - iOS:当您没有权利文件时,如何为您的应用程序实施关键警报?
- qml - 如何滚动直到在 Squish 测试(QT 应用程序)中可见特定对象?
- java - 简单的里程算法 - 抛出奇怪的错误?