Java 为什么int i=1024*1024*1024*1024编译时没有错误?
Java 为什么int i=1024*1024*1024*1024编译时没有错误?,java,int,Java,Int,int的限制是从-2147483648到2147483647 如果我输入 int i = 2147483648; 然后Eclipse将在“2147483648”下提示一条红色下划线 但如果我这样做: int i = 1024 * 1024 * 1024 * 1024; 它会很好的 public class Test { public static void main(String[] args) { int i = 2147483648;
int
的限制是从-2147483648到2147483647
如果我输入
int i = 2147483648;
然后Eclipse将在“2147483648”下提示一条红色下划线
但如果我这样做:
int i = 1024 * 1024 * 1024 * 1024;
它会很好的
public class Test {
public static void main(String[] args) {
int i = 2147483648; // error
int j = 1024 * 1024 * 1024 * 1024; // no error
}
}
也许这是Java中的一个基本问题,但我不知道为什么第二个变体不会产生错误;只需将4个数字相乘,并将其分配给一个整数,就会出现溢出。这与分配单个文本不同,后者将在编译时进行边界检查 导致错误的是越界文字,而不是赋值: 相比之下,
long
literal可以很好地编译:
System.out.println(2147483648L); // no error
请注意,实际上,结果仍然是在编译时计算的,因为1024*1024*1024*1024
是:
变成:
0: iconst_0
1: istore_1
请注意,结果(0
)只是简单地加载和存储,不会发生乘法
发自(感谢@ChrisK在评论中提出): 如果类型为
int
的十进制文字大于2147483648
(231),或者如果十进制文字2147483648
出现在一元减运算符()的操作数以外的任何位置,则这是编译时错误。
我不知道为什么第二种变体不会产生错误
您建议的行为(即,当计算生成的值大于可存储在整数中的最大值时,生成诊断消息)是一个特性。要使用任何功能,必须考虑该功能,将其视为一个好主意,设计、指定、实施、测试、记录并发送给用户
对于Java,该列表中的一个或多个事件没有发生,因此您没有该功能。我不知道是哪一个;您必须询问Java设计师
对于C#,所有这些事情都发生了——大约十四年前的现在——因此C#中相应的程序自C#1.0以来产生了一个错误。除了arshajii的答案之外,我想再展示一件事: 导致错误的不是赋值,而是文字的使用。 当你尝试
long i = 2147483648;
您会注意到,它还会导致编译错误,因为右侧仍然是int
-文本且超出范围
因此,具有
int
-值(包括赋值)的操作可能会溢出而不会出现编译错误(也不会出现运行时错误),但编译器无法处理那些太大的文本。1024*1024*1024
和2147483648
在Java中没有相同的值
实际上,2147483648
在Java中甚至不是一个值(尽管2147483648L
是)。编译器实际上不知道它是什么,也不知道如何使用它。所以它哀鸣
1024
在Java中是一个有效的int,一个有效的int
乘以另一个有效的int
,总是一个有效的int
。即使它不是您直观期望的值,因为计算将溢出
例子
考虑以下代码示例:
public static void main(String[] args) {
int a = 1024;
int b = a * a * a * a;
}
您希望这会生成编译错误吗?现在天气变得有点滑。如果我们把一个循环放在3个迭代中,然后在循环中相乘,会怎么样 编译器可以进行优化,但在进行优化时不能改变程序的行为
有关此案件实际处理方式的一些信息: 在Java和许多其他语言中,整数将由固定数量的位组成。不符合给定位数的计算将:;在Java中,计算基本上是以模2^32执行的,然后将值转换回有符号整数
其他语言或API使用动态位数(
BigInteger
,在Java中),引发异常或将值设置为神奇值,如not-a-number。a:,因为它不是错误
背景:乘法1024*1024*1024*1024
将导致溢出。溢出通常是一个bug。当溢出发生时,不同的编程语言会产生不同的行为。例如,C和C++将其称为符号整数的“未定义行为”,行为定义为无符号整数(取数学结果,加上<代码> uTunxMax + 1 < /COD>,只要结果是否定的,减去<代码> UTIN最大值+ 1 < /代码>,只要结果大于int
值的操作的结果不在允许的范围内,则从概念上讲,Java会添加或减去2^32,直到结果在允许的范围内。因此,该声明完全合法,没有错误。它只是不能产生你所希望的结果
您当然可以争论这种行为是否有用,以及编译器是否应该给您一个警告。我个人认为警告是非常有用的,但错误是不正确的,因为它是合法的Java。即使编译器通常会将计算“折叠”为单个值作为优化,如果结果是溢出,也不会这样做,因为任何优化都不应该改变程序的行为。它也不能解释
2147483648
:这个字面值毫无意义。Java也不会报告整数溢出——操作会无声地“失败”。@JacobKrall:C#会将此报告为缺陷,无论是否打开;所有只包含常量表达式的计算都会自动检查,除非在未检查的区域内;这些问题很难回答。一个“为什么不”的问题假设世界
long i = 2147483648;
public static void main(String[] args) {
int a = 1024;
int b = a * a * a * a;
}