Я сделал некоторый поиск на Google, но я, может казаться, не нахожу то, что я ищу. Я пытаюсь узнать некоторую подробную информацию о способе, которым арифметика работает в Java. Например, если Вы добавляете, что два longs вместе являются этим использованием того же оператора сложения, который используется при добавлении двух ints вместе? Кроме того, что продолжается под капотом, когда Вы смешиваете longs и ints в арифметических выражениях как это:
long result;
long operand a = 1;
int operand b = 999999999;
result = a + b;
Если бы кто-либо мог бы пролить некоторый свет на это или отправить ссылки на соответствующие статьи, которые были бы потрясающими.Спасибо!
Править: Спасибо за ответы до сих пор. Кроме того, действительно ли безопасно выполнить арифметику с различными примитивами, пока Вы присваиваетесь в переменную самого широкого типа примитива в Вашем выражении?
При смешивании типов int автоматически расширяется до long, а затем два long складываются для получения результата. Спецификация языка Java объясняет процесс для операций, содержащих различные примитивные типы.
В частности, это типы, до которых каждый примитив будет расширяться без необходимости преобразования:
Кроме того, безопасно ли выполнять арифметические операции с различными примитивами, если вы присваиваете переменную самого широкого примитивного типа в своем выражении?
Это зависит от того, что вы подразумеваете под безопасностью. Это, конечно, не избавит вас от необходимости учитывать возможность переполнения.
См: Преобразования и повышения
Согласно этому, ваш int
повышается до long
и затем оценивается.
То же самое происходит, например, с int
+ double
и остальными примитивами. т.е.
System.out( 1 + 2.0 );// prints 3.0 a double
Что касается оператора сложения я почти уверен, что это то же самое, но у меня нет никаких ссылок на него.
Быстрый просмотр исходников компилятора показывает, что они разные.
А именно iadd
для сложения int и ladd
для сложения long:
Смотрите этот пример кода:
$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
(для сложения long)
Также, безопасно ли выполнять арифметику с различными примитивами, если вы присваиваете переменную самого широкого примитивного типа в вашем выражении?
Да, и также "безопасно" выполнять арифметику с меньшими размерами, в том смысле, что они не ломают программу, вы просто теряете информацию.
Например, попробуйте добавить Integer.MAX_VALUE к Integer.MAX_VALUE
и посмотреть, что получится, или int x = ( int ) ( Long. MAX_VALUE - 1 );
это называется арифметическим продвижением. подробности см. на http://www.cafeaulait.org/course/week2/22.html