2015-12-05 2 views
3

Я думаю, что когда я прочитал статью Джошуа Блоха Эффективная Java, у меня создалось впечатление, что по соображениям эффективности следует избегать использования автобоксинга. Но я получаю противоречивую информацию, что могу доверять компилятору оптимальным образом использовать valueOf() и intValue(), когда я делаю неявное преобразование.Автобуксирование и математические выражения Java?

Так этот код я написал ниже

Integer capacity = 50103; 
Integer inventory = 40122; 

int available = capacity - inventory; 

Теоретически будет компилировать в тот же байт-код как код ниже.

Integer capacity = Integer.valueOf(50103); 
Integer inventory = Integer.valueOf(40122); 

int available = capacity.intValue() – inventory.intValue(); 

Это правда, что касается Java 7 и 8? Есть ли какая-либо причина явно вставить/удалить или оптимизировать компилятор для этого сейчас?

+0

Компилятор не «оптимизирует» это. Это всегда делает то, что показывает ваш второй пример. «Явно box/unbox» ничего не делает, он просто показывает, что происходит под капотом. – markspace

ответ

6

Это не оптимизация, это просто тот же код, написанный по-разному, но скомпилированный в тот же байт-код.

со следующими:

Integer capacity = 50103; 
Integer inventory = 40122; 
int available = capacity - inventory; 

как целые значения сначала упаковывается в Integer. Затем они деактивируются до int для выполнения вычитания. Это полностью эквивалентно второму фрагменту кода.

Нет особых причин явно указывать значения в этих случаях. Лучше оставить компилятор сделать это, потому что он обеспечивает более короткий, более читаемый код.

Это байт-код, созданный с помощью первого примера (JDK 1.8.0_60):

0: ldc   #2  // int 50103 
2: invokestatic #3  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
5: astore_1 
6: ldc   #4  // int 40122 
8: invokestatic #3  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
11: astore_2 
12: aload_1 
13: invokevirtual #5  // Method java/lang/Integer.intValue:()I 
16: aload_2 
17: invokevirtual #5  // Method java/lang/Integer.intValue:()I 
20: isub 
21: istore_3 
22: getstatic  #6  // Field java/lang/System.out:Ljava/io/PrintStream; 
25: iload_3 
26: invokevirtual #7  // Method java/io/PrintStream.println:(I)V 
29: return 

, где вы можете ясно видеть, что первый фрагмент был составлен в такой же, как второй фрагмент кода.

+0

Прохладный, спасибо за быстрый и тщательный ответ. – tmn

2

, что Autoboxing следует избегать по соображениям производительности

Это просто означает, что бокс и распаковка несет накладные расходы, и не должны быть выполнены без необходимости.

Не имеет значения, выполняется ли явная или явная операция бокса/распаковки; он скомпилируется с одним и тем же байтовым кодом.