开发者社区> 问答> 正文

Java 编译器检查整数类型的变量的初始化(声明并初始赋值)的原则是啥??报错

有人说,Java编译器编译时候,一般都要对 声明并初始化赋值的整数类型(byte, short, int, 和 long) 的变量初始化,进行检查,看看赋值大小是否超过变量的类型所容纳的范围。 如果超过范围, 报错:“从int转换到byte可能会有损失”, 或 “过大的整数: 2147483648”,从而停止编译。 如果要赋予的数值在允许范围之内,则编译通过此行代码。

如下代码 6个变量初始化赋值,全部超过了类型所容纳的范围。从编译信息可见,仅2处编译报错,未通过。

似乎找不出原则,

  1. 对十进制表示的 超值变量 short  s 和 byte b, 有时也不做检查(漏查)。
  2. 声明并初始化相应的包装类对象的时候,对参数 也是 有时检查,有时不检查 。
    public class A{	
    short s = 32800; //Shrt.MAX_VALUE: 32767 未报错
    byte b = 1208;  //Byte.MAX_VALUE:127 未报错
    int i = 2147483648; //Integer.MAX_VALUE 2147483647 报错
    int j = 0x80000000; //2147483648的16进制表示,未报错
    Integer  ii = new Integer(2147483648);//报错
    Integer  ji = new Integer("2147483648");//未报错
    }

    编译输出:

    D:\java\test\OS_China>javac A.java
    A.java:4: 错误: 过大的整数: 2147483648
    int i = 2147483648; //Integer.MAX_VALUE 2147483647 报错
            ^
    A.java:6: 错误: 过大的整数: 2147483648
    Integer  ii = new Integer(2147483648);//报错
                              ^
    2 个错误

     

展开
收起
爱吃鱼的程序员 2020-06-07 18:11:33 855 0
1 条回答
写回答
取消 提交回答
  • https://developer.aliyun.com/profile/5yerqm5bn5yqg?spm=a2c6h.12873639.0.0.6eae304abcjaIB
                        <p><img alt="" height="442" src="https://static.oschina.net/uploads/space/2018/0209/160653_MlXo_437238.jpg" width="677"></p> 
    

    将第4,6行注释掉之后,第2,3行编译报错。4,6行的错误信息是过大的整数,2,3行报错信息为不兼容的类型,可以看出java编译器认为这是两种不同的错误,对其检查的先后不同。

    int j = 0x80000000;

    这个数值表示的是-2147483648,并不超过整数范围,可以使用以下代码查看:

    Integer.toHexString(-2147483648);
    Integer  ji = new Integer("2147483648");

    最后这种情况更不会在编译时候检查,只能在运行时发现报错。

                                回复 <a class="referer" target="_blank">@tcxu</a>  : 1、关于16进制的问题可以去直接查看源码java.lang.Integer,其中:public static final int   MIN_VALUE = 0x80000000;
    

    2、我是将第4和第6行注释掉之后,第2和第3行才报错误的。两种错误的优先级不同。

                            2147483648 的16进制表示是: 0x80000000, 这个数值 高于 int 的上限/范围(整型 int 最大值 Integer.MAX_VALUE:2147483647)1。 因此应当报错。我将注释全部除掉,编译起来, 仍然只有两条错误信息。
                        
    
                            我的环境是:java version "1.8.0_162"
    

    Java(TM) SE Runtime Environment (build 1.8.0_162-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode).

                        <p>大原则:当一个编译阶段遇到错误后,就不会继续进行下一个阶段。</p>
    

    首先,字面常量值的处理,所以2147483648超出整形范围以后就会报错。

    然后,变量初始化的处理,所以隐式类型转换时就会报错。

    =========

    针对你的问题:

    1.不是漏检,而是之前的检查出错,就不进行下去了

    2.字符串的类型转换错误,只有运行时才能发现,编译阶段是无法得知的

                                回复 <a class="referer" target="_blank">@Shazi199</a>  : 谢谢你的提醒。
    

    问题是:int 型变量,不可能正确储存数值超过 Integer.MAX_VALUE 的正整数。如果不是动态情况(即,变量声明并初始赋值的情况),java 编译器是否都能检查出来?

                                回复 <a class="referer" target="_blank">@tcxu</a>  : 看来你不懂什么是补码,建议你好好学习一下再回过头来看这个问题
                        
    
                                回复 <a class="referer" target="_blank">@Shazi199</a>  : 输入的是出界的正整数(最大正整数 加 1),结果变成了  -2147483648  。虽然这个负值是最大负值,没出界。但是仍然是垃圾。比如:调用 System.out.println(Integer.MAX_VALUE +1); 输出也一样: -2147483648。难道这个输出不是垃圾吗?
                        
    
                                回复 <a class="referer" target="_blank">@tcxu</a>  : 没有出界啊,这个就是最大负值的表示形式
                        
    
                            好像还不全是这样。有时根本就不检查(或检查不出来)。 如,public class B{	
    

    static int j = 0x80000000; public static void main(String args[]){ System.out.println(j); } } 编译通过,输出的是 -2147483648 (垃圾), 因为初始值出界,变为最大负值。

    2020-06-08 11:16:51
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载