在我的工作环境中,我们被迫从Java 1.6升级到Java 1.8。我们确实修复了此升级中引入的大部分代码破坏,但我们现在偶然发现了以下内容:
在Java 1.6中正确执行:
class TestViz extends TestFrame
{
// this class is abstract
}
class TestChart extends TestViz
{
}
class MyClassTest extends JUnit
{
public MyTest()
{
TestChart chartClone = (TestChart) chart.duplicate();
}
}
现在chart.duplicate()
会返回TestFrame
,因此会播放。
不幸的是,使用Java 1.8时,此代码失败,使用java.lang.ClassCastException
。
有人知道关于抽象类转换的变化,以及可能如何修复此代码?
谢谢。
修改
错误消息显示:
"TestFrame cannot be cast to TestChart"
答案 0 :(得分:2)
发生错误是因为您尝试执行无效的转换操作。
您的TestChart
类是TestFrame
的子类。这意味着以下演员表有效:
TestChart chart = new TestChart();
TestFrame frame = (TestFrame) chart;
这是因为Java将处理您的chart
对象,就好像它是TestFrame
(它是!),因此TestChart
的任何特定变量或方法都不会在这里显示(因为它们不属于TestFrame
)。
然而,当你试图向相反的方向前进时,做一个类似
的演员表TestFrame frame = new TestFrame();
TestChart chart = (TestChart) frame;
您将获得ClassCastException
,因为您无法以这种特定方式处理TestFrame
课程。在TestChart
(甚至TestViz
)中声明的方法和变量不会出现在frame
对象中(因为,猜猜是......它是TestFrame
},而不是TestChart
!)
这是继承在Java中的工作方式。您可以通过其超级类之一广泛地引用对象,但您可以从不通过其 sub 类之一引用对象因为你会试图缩小范围而不是语言可以支持你。
如果考虑到duplicate()
返回的对象属于TestFrame
类型,您可以进行测试,那么您的代码就像
TestFrame chartClone = chart.duplicate();
这应该可以正常工作。另一个解决方案是更改duplicate()
方法的签名并返回TestChart
类型的对象,因此不需要强制转换。