V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
amiwrong123
V2EX  ›  Java

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

  •  
  •   amiwrong123 · 2019-12-01 12:02:16 +08:00 · 3926 次点击
    这是一个创建于 1827 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    aguesuka
        1
    aguesuka  
       2019-12-01 12:14:38 +08:00
    泛型不一样 左边是 Class<Integer> 右边是 Class<String>
    aguesuka
        2
    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
        3
    momocraft  
       2019-12-01 12:39:26 +08:00
    jawa 的泛型默認是不變 (invariant): Class<String>和 Class<Integer>沒有共通的祖先類, 是兩個 "完全無關" 的類型. 即使 String 和 Interger 有共同的祖先類 (Object).
    geelaw
        4
    geelaw  
       2019-12-01 12:52:59 +08:00   ❤️ 5
    @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
        5
    ZredoC  
       2019-12-01 13:03:27 +08:00
    想了半天,发现想歪了

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

    而是为啥不能用 == 比较

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

    。。

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

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

    光记着比地址值,忽视了比的是啥
    ZredoC
        6
    ZredoC  
       2019-12-01 13:07:12 +08:00
    打扰了,胡言乱语一通
    看#4
    SoloCompany
        7
    SoloCompany  
       2019-12-01 14:00:55 +08:00 via iPhone
    只有赋值相容才可以用==比较,也就是说要么 a 能赋值给 b,或者相反,否则就是编译是错误,想明白这点是为什么就不难理解了
    amiwrong123
        8
    amiwrong123  
    OP
       2019-12-01 15:35:46 +08:00
    @aguesuka
    boolean result = ((Class) String.class) == ( Integer.class); 所以右边的就可以隐式转换为泛型的原生类型了。
    amiwrong123
        9
    amiwrong123  
    OP
       2019-12-01 15:36:50 +08:00
    @geelaw
    谢谢解答,直接解开了我的疑惑
    amiwrong123
        10
    amiwrong123  
    OP
       2019-12-01 15:37:15 +08:00
    @ZredoC
    哈哈哈哈,不打扰不打扰
    amiwrong123
        11
    amiwrong123  
    OP
       2019-12-01 15:37:54 +08:00
    @SoloCompany
    确实,赋值相容,就是代表可以隐式转换。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1051 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 23:08 · PVG 07:08 · LAX 15:08 · JFK 18:08
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.