Java类型转换疑问:Tuple2转EasyTuple2为何有时报错有时可行?
为什么两种强转场景结果截然不同?
这其实是Java中编译时类型与运行时类型不一致导致的典型案例,咱们拆开两种场景逐一分析:
1. 直接强转抛出ClassCastException的原因
看你注释掉的这段代码:
Tuple2<String, String> tuple2 = new Tuple2<>("abcd", "1234"); EasyTuple2<String> easyTuple2 = (EasyTuple2<String>) tuple2;
变量tuple2的编译时类型是Tuple2,但它的运行时实际类型也确实是Tuple2——从创建那一刻起,它就是一个纯粹的Tuple2实例,和EasyTuple2没有任何继承实例关系。Java运行时会严格校验对象的真实类型,父类实例无法直接强转为子类类型,所以必然抛出类型转换异常。
2. getSelf方法中强转成功的原因
再看abcd.getSelf("efg", "567")的调用逻辑:
- 核心前提:
abcd本身是EasyTuple2的实例! - 当调用
super.getSelf(t1, t2)时,父类方法里返回的this,本质就是当前调用方法的EasyTuple2对象本身(this始终指向方法的实际调用者)。 - 虽然父类方法的返回类型声明为
Tuple2<T, T>,但它指向的真实运行时对象还是EasyTuple2。此时把它强转回EasyTuple2<T>,只是把一个“披着父类类型外衣的子类对象”还原成它本来的类型,完全符合Java的类型规则,所以不会报错。
简单总结:前者是「真父类对象转子类」,属于非法转换;后者是「子类对象被父类类型引用后转回来」,本质是还原对象的真实类型,完全合法。
内容的提问来源于stack exchange,提问作者Guo
相关产品推荐
相关产品推荐

