[英]Java arithmetic int vs. long
我在谷歌上做了一些搜索,但似乎找不到我要找的东西。 我试图找出一些关于 Java 中算术工作方式的详细信息。 例如,如果您将两个 long 相加,这是否使用与将两个 int 相加时使用的相同加法运算符? 此外,当你在这样的算术表达式中混合 longs 和 ints 时,引擎盖下发生了什么:
long result;
long operand a = 1;
int operand b = 999999999;
result = a + b;
如果有人可以对此有所了解或发布相关文章的链接,那就太棒了。 谢谢!
编辑:感谢您到目前为止的答复。 此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
混合类型时,int 会自动加宽为 long,然后将两个 long 相加以产生结果。 Java 语言规范解释了包含不同原始类型的操作的过程。
具体来说,这些是每个原始类型将扩展到而不需要强制转换的类型:
请参阅: 转换和促销
据此,您的int
被提升为long
然后被评估。
例如, int
+ double
和其他原语也会发生同样的情况。 IE。
System.out( 1 + 2.0 );// prints 3.0 a double
至于加法运算符,
我几乎是一样的,但我没有任何参考。
快速查看编译器的源代码就会发现它们是不同的。
即iadd
表示 int 加法,而ladd
表示长加法:
请参阅此示例代码:
$cat Addition.java
public class Addition {
public static void main( String [] args ) {
int a = Integer.parseInt(args[0]);
long b = Long.parseLong(args[0]);
// int addition
int c = a + a;
// long addition
long d = a + b;
}
}
$javac Addition.java
$
编译时生成的字节码是这样的:
$javap -c Addition
Compiled from "Addition.java"
public class Addition extends java.lang.Object{
public Addition();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aload_0
1: iconst_0
2: aaload
3: invokestatic #2; //Method java/lang/Integer.parseInt:(Ljava/lang/String;)I
6: istore_1
7: aload_0
8: iconst_0
9: aaload
10: invokestatic #3; //Method java/lang/Long.parseLong:(Ljava/lang/String;)J
13: lstore_2
14: iload_1
15: iload_1
16: iadd
17: istore 4
19: iload_1
20: i2l
21: lload_2
22: ladd
23: lstore 5
25: return
}
看看第16
行它说: iadd
(用于 int 加法)而第22
行说ladd
(用于长加法)
此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
是的,而且用较小的尺寸执行算术也是“安全的” ,从某种意义上说,它们不会破坏程序,只会丢失信息。
例如,尝试将Integer.MAX_VALUE添加到Integer.MAX_VALUE
以查看会发生什么,或者int x = ( int ) ( Long.MAX_VALUE - 1 );
此外,只要您在表达式中分配给最宽的原始类型的变量,使用不同的原始类型执行算术是否安全?
这取决于你所说的安全是什么意思。 它当然不会避免您需要考虑溢出的可能性。
这称为算术提升。 详情请查看http://www.cafeaulait.org/course/week2/22.html
int a=5;
long b=10;
a+=b;
System.out.println(a);
主要区别在于a = a + b
没有进行类型转换,因此编译器会因为您没有进行类型转换而生气。 但是对于a += b
,它真正做的是将b
类型转换为与a
兼容a
类型。
这个简单的例子可以消除java中算术运算时对数据类型转换的疑惑。
byte a = 1;
short b = 1;
System.out.println(a+b); //Output = 2
Object o = a+b; //Object becomes int
System.out.println(o.getClass().getName()); //Output = java.lang.Integer
int c = 1;
System.out.println(a+b+c); //Output = 3
o = a+b+c; //Object becomes int
System.out.println(o.getClass().getName()); //Output = java.lang.Integer
long d = 1l;
System.out.println(a+b+c+d); //Output = 4
o = a+b+c+d; //Object becomes long
System.out.println(o.getClass().getName()); //Output = java.lang.Long
float e = 1.0f;
System.out.println(a+b+c+d+e); //Output = 5.0
o = a+b+c+d+e; //Object becomes float
System.out.println(o.getClass().getName()); //Output = java.lang.Float
double f = 1.0;
System.out.println(a+b+c+d+e+f); //Output = 6.0
o = a+b+c+d+e+f; //Object becomes double
System.out.println(o.getClass().getName()); //Output = java.lang.Double
以下是java中根据范围的数据类型顺序:
byte<short<int<long<float<double
这是扩大发生的顺序。
注意: float 的范围比 long 大,但尺寸更小。
答案指出算术提升。 但考虑到这一点,我陷入了以下陷阱(我很惭愧),我想在这里指出:如果对我来说有两个以上的操作数,似乎计算是从左到右执行的,如果实际有两个,则会发生算术提升焦点中的操作数具有不同的类型。 因此,以下代码对 s1 和 s2 产生不同的结果。 我对此的解释是:在计算 s1 时,首先将 a 和 b 作为两个整数相加(并且发生溢出),然后将 c(a long)的结果相加。 在计算 s2 时,首先添加 c 和 b(如 long),然后添加 a(提升为 long),因此不会发生溢出。
final int a = Integer.MAX_VALUE;
final int b = 1;
final long c = 1L;
final long s1 = a + b + c;
final long s2 = c + b + a;
System.out.println("s1=" + s1 + ", s2=" + s2);
输出将为: s1=-2147483647, s2=2147483649
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.