有人说,Java编译器编译时候,一般都要对 声明并初始化赋值的整数类型(byte, short, int, 和 long) 的变量初始化,进行检查,看看赋值大小是否超过变量的类型所容纳的范围。 如果超过范围, 报错:“从int转换到byte可能会有损失”, 或 “过大的整数: 2147483648”,从而停止编译。 如果要赋予的数值在允许范围之内,则编译通过此行代码。
如下代码 6个变量初始化赋值,全部超过了类型所容纳的范围。从编译信息可见,仅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 个错误
<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 (垃圾), 因为初始值出界,变为最大负值。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。