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

关于 Java 的 byte 型和 int 型类型之间比较的问题

  •  
  •   shayuvpn0001 · 2018-08-20 11:29:59 +08:00 · 7289 次点击
    这是一个创建于 2286 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在看 Java,关于类型比较,有一个问题一直想弄清楚。先直接上代码:

    public class Main {
        public static void main(String[] args) {
    	// write your code here
            int p = (int)(25);
            byte q = (byte)(25);
            int result = 0;
            if (p == q) {
                result = 1;
            }else{
                result = 2;
            }
            System.out.println("result is "+result);
            return;
        }
    }
    

    当一个 byte 类型变量与 int 类型变量进行比较时,head first java 上面的解释是:
    The == operator can be used to compare two variables of any kind, and it simply compares the bits.

    if (a == b) {...} looks at the bits in a and b and returns true if the bit pattern is the same (although it doesn ’ t care about the size of the variable, so all the extra zeroes on the left end don ’ t matter).

    如果按照这个解释,那么==操作符执行的动作应该是将 byte 的 8bit 与 int 的最低位 8bit 逐位比较,如果两者一模一样,则返回 true。

    然而我记得以前看过其他语言,还有两种可能的操作: 第一种是 cast,将占用空间小的变量转换为空间大的变量,比如将本例中 byte 类型的 p 直接 cast 为 int 类型的变量,这中间隐藏了一次强制类型转换的操作。 第二种是 scale up and padding,先将 byte 的 1 字节转换为 int 的 4 字节,然后将 byte 转换后的 int 类型高 2 字节填充为低 2 字节的符号位。 我尝试过将上面代码替换为

            int p = (int)(-127);
            byte q = (byte)(-127);
    

    打印结果显示 p 和 q 仍然相等,这样的话,第二种应该是不成立的。

    又用 c,C#试验,结果类似,唯一不同的是 C#将 byte 类型处理为 unsigned 类型,不允许赋一个负值。

    综上,对于此种比较,一共有三种解释:head first 解释,cast 解释,scale up and padding 解释.

    如果按照 head first 的解释,那么 byte 型值 6 应该与整形值 53254 相等,因为前者的二进制是 0000 0110,而后者的二进制值是 1101 0000 0000 0110,因为按照该解释是逐位比较,高位不比。用代码进行试验:

            int p = (int)(53254);
            byte q = (byte)(6);
    

    输出结果是:2,也就是两者并不相等。

    想请各位帮我看看,这个是怎么回事?

    5 条回复    2018-08-20 13:59:58 +08:00
    honeycomb
        1
    honeycomb  
       2018-08-20 11:46:57 +08:00 via Android   ❤️ 1
    在 Java 里 53254 的 int 和 6 的 byte 作==的比较时,会自动类型转换为 53254 的 int 和 6 的 int,所以两者不相等。
    honeycomb
        2
    honeycomb  
       2018-08-20 11:50:36 +08:00 via Android
    -127 的 byte 强制转换为 int 后则是-127 的 int,但 int 的 6 并不是 int 的 53254。

    如果你用按位与的方式把-127 的 byte 转换成 int,则输出的符号位依然是 0
    szq8014
        3
    szq8014  
       2018-08-20 12:46:53 +08:00   ❤️ 2
    Integer.toBinaryString 打印两者试试,看看是不是和你的期望一样。

    jvm 里面的操作数栈是 32 位的,所以 byte, short, int 三兄弟进去大家都一样按 32 位处理,顶多 byte, short 有一个 range check。。

    [oracle 对 JVM 操作数栈定义]( https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.6.2)

    [SO 提问,为啥 byte, short 操作的时候要通过 bipush, sipush 来 expand]( https://stackoverflow.com/questions/18469326/why-jvm-expands-byte-short-to-int-before-pushing-on-stack
    Lonely
        4
    Lonely  
       2018-08-20 13:05:48 +08:00   ❤️ 1
    这种问题,可以去看 JavaSE 的 Specification 啊,不要自己在那瞎猜。。。
    If the operands of an equality operator are both of numeric type, or one is of numeric type and the other is convertible (§5.1.8) to numeric type, binary numeric promotion is performed on the operands (§5.6.2).
    (出自 JavaSE8 Specification 15.21.1 )
    shayuvpn0001
        5
    shayuvpn0001  
    OP
       2018-08-20 13:59:58 +08:00
    @honeycomb 谢谢,那就是默认有一次操作将 byte 类型 cast 为 int 类型,然后比较了,那这么看来 head first 里面说的不准确。

    @szq8014
    @Lonely
    恩,刚看到。里面说的 signed extension 和 zero extension 应该就是高位按符号位补齐还是按 0 补齐了。JVM 和 Java Language Spec.我确实是想看,我以前是写 C#的,知道有这些东西,但细节方面还是不了解。现在是急着面试,也没办法全看,只能需要的时候看一点是一点了。为了追求速度,也只能有问题就直接上来问,厚着脸皮当伸手党了。

    按照 @szq8014 给的 JVM Spec.中 Table 2.3 Actual and Computational types in the JVM 的描述,我理解为 JVM 在做计算的时候是将 boolean, byte, char, short 都用 int 来处理的。如果按照 @Lonely 指出的有 binary numeric promotion,那么我理解比较一个 long 和 byte 比较也会发生 binary numeric promotion。

    @szq8014 提到了使用 Integer.toBinaryString 打印观察变量的实际情况,我在想如果直接观察编译后生成的字节码应该也能看出端倪吧(虽然我现在还没仔细了解字节码)

    还有一点就是我想了解一下这个 binary promotion 或者说 signed/zero extension 是在编译器编译成字节码时就完成了还是在 JVM 运行的时候才完成的。

    sorry,唠唠叨叨说了一大堆。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1047 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 23:06 · PVG 07:06 · LAX 15:06 · JFK 18:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.