限制int
是从-2147483648到2147483647.
如果我输入
int i = 2147483648;
Run Code Online (Sandbox Code Playgroud)
那么Eclipse将在"2147483648"下面提示一个红色下划线.
但如果我这样做:
int i = 1024 * 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)
它会编译好.
public class Test {
public static void main(String[] args) {
int i = 2147483648; // error
int j = 1024 * 1024 * 1024 * 1024; // no error
}
}
Run Code Online (Sandbox Code Playgroud)
也许这是Java中的一个基本问题,但我不知道为什么第二个变量不会产生错误.
ars*_*jii 232
这句话没有错; 你只是将4个数字相乘并将其分配给一个int,恰好就是溢出.这与分配单个文字不同,后者将在编译时进行边界检查.
导致错误的是越界文字,而不是作业:
System.out.println(2147483648); // error
System.out.println(2147483647 + 1); // no error
Run Code Online (Sandbox Code Playgroud)
相比之下,long
文字可编译良好:
System.out.println(2147483648L); // no error
Run Code Online (Sandbox Code Playgroud)
请注意,实际上,结果仍然是在编译时计算的,因为它1024 * 1024 * 1024 * 1024
是一个常量表达式:
int i = 1024 * 1024 * 1024 * 1024;
Run Code Online (Sandbox Code Playgroud)
变为:
0: iconst_0
1: istore_1
Run Code Online (Sandbox Code Playgroud)
请注意,0
只需加载和存储result(),不会发生乘法.
来自JLS§3.10.1(感谢@ChrisK在评论中提出它):
如果类型的十进制文字
int
大于2147483648
(2 31),或者十进制文字2147483648
出现在除一元减号运算符(第15.15.4节)的操作数之外的任何地方,则为编译时错误.
Cru*_*her 43
1024 * 1024 * 1024 * 1024
并且2147483648
在Java中没有相同的值.
实际上,在Java中,它2147483648
不是一个值(尽管2147483648L
是).编译器实际上不知道它是什么,或者如何使用它.所以它发牢骚.
1024
是Java中的有效int,有效int
乘以另一个有效int
,总是有效的int
.即使它与您直观期望的值不同,因为计算会溢出.
请考虑以下代码示例:
public static void main(String[] args) {
int a = 1024;
int b = a * a * a * a;
}
Run Code Online (Sandbox Code Playgroud)
您是否希望这会产生编译错误?现在变得有点滑.
如果我们放置一个循环3次迭代并在循环中相乘怎么办?
允许编译器进行优化,但它不能在程序执行时更改程序的行为.
有关如何实际处理此案例的一些信息:
在Java和许多其他语言中,整数将由固定数量的位组成.不符合给定位数的计算将溢出 ; 计算基本上是在Java中执行模数 2 ^ 32,之后将值转换回有符号整数.
其他语言或API使用动态数量的位(BigInteger
在Java中),引发异常或将值设置为魔术值,例如非数字.
Eri*_*ert 16
我不知道为什么第二个变体没有产生错误.
您建议的行为 - 即,当计算生成的值大于可以存储在整数中的最大值时生成诊断消息 - 是一项功能.对于您使用任何功能,必须考虑该功能,被认为是一个好主意,设计,指定,实施,测试,记录并发送给用户.
对于Java,该列表中的一个或多个内容没有发生,因此您没有该功能.我不知道哪一个; 你必须问一个Java设计师.
对于C#来说,所有这些事情确实发生了 - 大约十四年前 - 所以C#中的相应程序自C#1.0以来就产生了错误.
pie*_*t.t 12
除了arshajii的答案,我想再展示一件事:
不是导致错误的赋值,而是简单地使用文字.当你尝试
long i = 2147483648;
Run Code Online (Sandbox Code Playgroud)
您会注意到它也会导致编译错误,因为右侧仍然是int
-literal且超出范围.
所以带有int
-values的操作(包括赋值)可能会在没有编译错误的情况下溢出(并且没有运行时错误),但是编译器无法处理那些太大的文字.
归档时间: |
|
查看次数: |
15497 次 |
最近记录: |