为什么 Class 对象不能用==比较呢,但强转 Object 后就可以了?

2019-12-01 12:02:16 +08:00
 amiwrong123

System.out.println(Integer.class == String.class);这句就是不能通过编译的。

但如果 System.out.println((Object) Integer.class == (Object)String.class);就可以通过编译了。(返回 false,顺便说一句)

Integer.class 返回的不就是一个在堆上的 Class 对象吗,只不过它的类型是Class<Integer>,为啥它们两个不能用作操作符==比较呢?

3934 次点击
所在节点    Java
11 条回复
aguesuka
2019-12-01 12:14:38 +08:00
泛型不一样 左边是 Class<Integer> 右边是 Class<String>
aguesuka
2019-12-01 12:20:17 +08:00
// ok
boolean result = ((Class) String.class) == ( Integer.class);
// 报错
boolean result1 = ( String.class) == ( Integer.class);
// 报错
boolean result2 = new ArrayList<String>() == new ArrayList<Integer>();
momocraft
2019-12-01 12:39:26 +08:00
jawa 的泛型默認是不變 (invariant): Class<String>和 Class<Integer>沒有共通的祖先類, 是兩個 "完全無關" 的類型. 即使 String 和 Interger 有共同的祖先類 (Object).
geelaw
2019-12-01 12:52:59 +08:00
@aguesuka #1 @momocraft #3 其实这并不是重点,Class<Integer> 和 Class<String> 都是 Object 的派生类(并不能说是“完全无关”),楼主想要问为什么引用比较不直接假设隐式转换为 Object 后引用比较。

根据 JLS 12:

15.21.3 Reference Equality Operators == and !=
If the operands of an equality operator are both of either reference type or the null type, then the operation is object equality.
It is a compile-time error if it is impossible to convert the type of either operand to the type of the other by a casting conversion (§5.5). The run-time values of the two operands would necessarily be unequal (ignoring the case where both values are null).
...

如果 a == b 里面 a、b 的编译期类型分别是非 String 的引用类型 A、B,则必须存在 A 到 B 的隐式转换或存在 B 到 A
的隐式转换,否则编译失败。这是一个人为限制,动机主要是绝大多数情况下这两个的比较结果都是“不引用相等”。

只需要把一个比较运算数转换为 Object 即可编译成功。
ZredoC
2019-12-01 13:03:27 +08:00
想了半天,发现想歪了

楼主问的不是为啥 Integer.class 和 String.class 的 Class 对象的泛型不一样导致==结果返回 false

而是为啥不能用 == 比较

所以 #3 没有共同祖先类 的说法感觉靠谱

。。

== 是用于比较基本和引用数据类型的关系运算符

Class 对象俩都不算的吧,所以编译报错了

光记着比地址值,忽视了比的是啥
ZredoC
2019-12-01 13:07:12 +08:00
打扰了,胡言乱语一通
看#4
SoloCompany
2019-12-01 14:00:55 +08:00
只有赋值相容才可以用==比较,也就是说要么 a 能赋值给 b,或者相反,否则就是编译是错误,想明白这点是为什么就不难理解了
amiwrong123
2019-12-01 15:35:46 +08:00
@aguesuka
boolean result = ((Class) String.class) == ( Integer.class); 所以右边的就可以隐式转换为泛型的原生类型了。
amiwrong123
2019-12-01 15:36:50 +08:00
@geelaw
谢谢解答,直接解开了我的疑惑
amiwrong123
2019-12-01 15:37:15 +08:00
@ZredoC
哈哈哈哈,不打扰不打扰
amiwrong123
2019-12-01 15:37:54 +08:00
@SoloCompany
确实,赋值相容,就是代表可以隐式转换。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/624756

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX