Java arithmetic int vs. long
我已经在Google上进行了一些搜索,但似乎找不到我想要的东西。 我试图找出有关Java中算术工作方式的详细信息。 例如,如果您将两个long累加在一起,这是否使用了将两个int累加在一起时使用的同一加法运算符? 同样,当您将long和int混合在这样的算术表达式中时,到底发生了什么:
1 2 3 4 5 | long result; long operand a = 1; int operand b = 999999999; result = a + b; |
如果有人能对此有所启发或发布指向相关文章的链接,那将是很棒的。 谢谢!
编辑:感谢到目前为止的答复。 另外,只要您将表达式赋值给表达式中最宽泛的原始类型的变量,对不同的原始进行算术运算是否安全?
当混合类型时,int会自动加长到一个long,然后将两个long相加以产生结果。 Java语言规范说明了包含不同基本类型的操作的过程。
具体来说,以下是每个基本体将扩展为的类型,而无需强制转换:
- 字节到short,int,long,float或double
- 短至int,long,float或double
- char转换为int,long,float或double
- int转换为long,float或double
- 长时间漂浮或翻倍
- 浮动到两倍
另请:转化和促销
据此,您的
例如,
1 |
至于加法运算符,我几乎是一样的,但是我没有任何参考。 strike>
快速查看编译器的源代码可以发现它们是不同的。
即
请参见以下示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
编译时生成的字节码是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | $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 } |
查看第
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
是的,以较小的尺寸执行算术也是"安全的",从某种意义上说,它们不会破坏程序,只会丢失信息。
例如,尝试将Integer.MAX_VALUE添加到
这称为算术提升。有关详细信息,请访问http://www.cafeaulait.org/course/week2/22.html
Also, is it safe to perform arithmetic with different primitives so long as you are assigning into a variable of the widest primitive type in your expression?
这取决于您所指的安全。当然,这不会避免您需要考虑溢出的可能性。
1 2 3 4 |
主要区别在于,使用
但是对于
这个简单的示例可以清除在Java中进行算术运算时对数据类型转换的疑问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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中范围的数据类型顺序:
1 | byte<short<int<long<float<double |
这是扩展发生的顺序。
注意:float的范围比long长,但大小较小。
答案指出了算术提升。但是考虑到这一点,我陷入了以下陷阱(我感到羞耻),在这里我要指出:
如果对我来说有两个以上的操作数,则似乎计算是从左到右执行的,并且如果焦点上的实际两个操作数具有不同的类型,则会进行算术提升。
因此,以下代码对s1和s2产生不同的结果。我对此的解释是:
在计算s1时,首先将a和b作为两个整数相加(并且发生溢出),然后将其与c的结果(一个long)相加。
在计算s2时,首先将c和b相加(一样长),然后将a相加(一样长地提升),因此不会发生溢出。
1 2 3 4 5 6 |
输出将是: