2014-12-26 2 views
0

Рассмотрим следующий код:Ошибка компиляции в программе Java

public class A { 

    public static void main(String[] args) { 

     Integer i = 9; 
     char c = 'a'; 
     c = c*i; \\ compilation error 
     c *= i; 
     System.out.println(c); 
    } 

} 

Мои сомнения c = c*i, дает ошибку компиляции, но почему бы не c *= i, хотя я знаю, что оба выражения эквивалентны.

+3

'с * i' является' 'int', когда с * = i' является' char' –

ответ

2

Функционально выражения c = c * i; и c *= i; действительно эквивалентны - они должны делать то же самое.

Однако вы делаете расчеты с различными типами здесь (int и char) и языком программирования Java имеет правило о том, что преобразования между типами выполняются автоматически (без броска), и когда вы должны явно сделать бросок.

Эти преобразования подробно описаны в chapter 5 Спецификации языка Java.

Умножение на char и int в c * i приводит к значению типа int, как описано в 5.6.2 Binary Numeric Promotion. Затем вы пытаетесь присвоить это char, который является narrowing primitive conversion, который не может быть выполнен без приведения.

15.26.2 Compound Assignment Operators объясняет такие операторы, как *=. Этот пункт объясняет: выражение присваивания

Соединения формы E1 op= E2 эквивалентно E1 = (T) ((E1) op (E2)), где T является типом E1, за исключением того, что E1 вычисляются только один раз.

Обратите внимание, что приведение к типу левой переменной неявно выполняется. Так что если вы делаете c *= i;, это эквивалентно:

c = (char)(c * i); 

Бросок от int к char делается неявно.

0

c = c * i; // ошибка компиляции

Причина, по которой вы получаете ошибку компиляции, состоит в том, что c*i будет оцениваться как целое, и вы пытаетесь присвоить его символу.
Где как c*=i оценивается как знак, следовательно, действительное назначение.

Существует принципиальная разница между c*i и c*=i. c*i всегда integer, как i является integer, в то время как c*=i является c=(char)c*i

+0

Но оба выражения эквивалентны правильно ... то почему один оцениваются как полукокс а другой как int – Leo

+0

Я обновил свой ответ, выделив разницу между ними. –

0

случае -1: c = c*i;

Здесь вы получите ошибку компиляции, так как результат c * i будет int, которые не могут быть отнесены к полукокса ,

случай-2: c *= i;

Теперь этот случай немного интересно. Глядя на байт-код:

9: iload_2 // load c as an integer --> here is the critical section 
    10: aload_1 // load reference i 
    14: imul  // multiply 1 and 2 
    15: i2c  // convert integer back to char 
    16: istore_2 // store value in c 

    LocalVariableTable: 
    Start Length Slot Name Signature 
     0  25  0 args [Ljava/lang/String; 
     6  19  1  i Ljava/lang/Integer; 
     9  16  2  c C 
+0

Спасибо, но пошла над моей головой ... – Leo

+0

@ Leo - Проверьте * Jesper's/Erans * ответ. Посмотрите на JLS и вернитесь, чтобы увидеть здесь байтовый код :) – TheLostMind

2

два выражения являются не эквивалентны.

JLS 15.26.2 объясняет:

Выражение присваивания соединение вида E1 оп = E2 эквивалентно E1 = (T) ((Е1) оп (E2)), где Т представляет собой тип E1 , за исключением того, что E1 оценивается только один раз.

Поэтому:

c *= i; 

эквивалентно

c = (char) (c * i); 

, который не то же самое, как

c = c * i; 
0

Если я помню правильно, составные операторы присваивания (+=, -= и т. Д.) Имеют неявный тип приведения в действие.

Следовательно, при использовании c *= i;, оператор присваивания соединения способствует переменному соответственно (в случае char к int), и автоматически преобразует результат обратно в char.

См: Java: compound assignment and expression based type promotion

0

(c *= i)==(c = (char) (c * i)); 
 

 
Both Are Same Result Print But (c = c*i) invalid Sytex i is Integer anc c char : 
 
here need a possibaly loss precision integar and char. 
 
you need 
 

 
c = (char) (c * i)