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 < /代码>,只要结果大于 UTIN最大值)。p> 在Java的情况下,如果具有
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;
}