我在google上做了一些搜索,但我似乎无法找到我正在寻找的东西。我试图找出有关算术在Java中运行方式的一些详细信息。例如,如果将两个长片一起添加,则使用在将两个整数添加到一起时使用的相同加法运算符?另外,当你在这样的算术表达式中混合long和int时,会发生什么:
long result;
long operand a = 1;
int operand b = 999999999;
result = a + b;
如果有人能够对此有所了解或发布相关文章的链接,那将是非常棒的。谢谢!
编辑:感谢您的回复。另外,只要在表达式中分配最宽基元类型的变量,用不同的基元执行算术是否安全?
答案 0 :(得分:15)
当混合类型时,int会自动加宽为long,然后添加两个long以生成结果。 Java Language Specification解释了包含不同主要类型的操作过程。
具体来说,这些类型是每个主要的扩展到不需要演员的类型:
答案 1 :(得分:7)
请参阅:Conversions and promotions
根据这一点,您的int
会提升为long
,然后进行评估。
例如,int
+ double
和其他原语也是如此。即
System.out( 1 + 2.0 );// prints 3.0 a double
至于加法运算符我几乎是相同的,但我没有任何参考。
编译器源代码的快速浏览显示它们不同。
即添加int iadd
和长添加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 );
答案 2 :(得分:3)
此外,只要您在表达式中指定最宽基元类型的变量,用不同的基元执行算术是否安全?
这取决于你的安全意味着什么。它当然不会避免你需要考虑溢出的可能性。
答案 3 :(得分:3)
这称为算术推广。有关详细信息,请查看http://www.cafeaulait.org/course/week2/22.html
答案 4 :(得分:2)
int a=5;
long b=10;
a+=b;
System.out.println(a);
主要区别在于a = a + b
,没有进行类型转换,因此编译器因为没有进行类型转换而对你生气。
但是对于a += b
,它真正做的是将b
类型转换为与a
兼容的a
类型。
答案 5 :(得分:1)
这个简单的例子可以清除对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长,但是尺寸更小。
答案 6 :(得分:0)
答案指出了算术提升。但是考虑到这一点,我陷入了以下陷阱(我感到羞耻),在这里我要指出: 如果对我来说有两个以上的操作数,则似乎计算是从左到右执行的,并且如果焦点上的实际两个操作数具有不同的类型,则会进行算术提升。 因此,以下代码对于s1和s2产生不同的结果。我对此的解释是: 在计算s1时,首先将a和b作为两个整数相加(并且发生溢出),然后向c的结果(一个long)中相加。 在计算s2时,首先将c和b相加(只要很长),然后再相加a(提升很长时间),这样就不会发生溢出。
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