Why don 't Java' s +=, -=, *=, /= operatorzy przydziałów złożonych wymagają odlewania?

Do dzisiaj myślałem, że na przykład:

i += j;

Był tylko skrótem do:

i = i + j;

Ale jeśli spróbujemy tego:

int i = 5;
long j = 8;

Wtedy i = i + j; nie skompiluje, ale i += j; skompiluje dobrze.

Czy to znaczy, że w rzeczywistości i += j; jest skrótem od czegoś takiego i = (type of i) (i + j)?

Author: GMachado, 2012-01-03

11 answers

Jak zawsze z tymi pytaniami, JLS posiada odpowiedź. W tym przypadku §15.26.2 operatory przypisania złożonego . "Ekstrakt": {]}

Złożone wyrażenie przypisania postaci E1 op= E2 jest równoważne E1 = (T)((E1) op (E2)), Gdzie T jest typem E1, z tym że E1 jest oceniane tylko raz.

Przykład przytoczony z §15.26.2

[...] następujący kod jest poprawny:

short x = 3;
x += 4.6;

I powoduje, że x ma wartość 7, ponieważ jest równoważne:

short x = 3;
x = (short)(x + 4.6);
Innymi słowy, twoje założenie jest poprawne.
 2484
Author: Lukas Eder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-09 10:54:12

Dobrym przykładem tego odlewania jest użycie * = lub / =

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

Lub

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

Lub

char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'

Lub

char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'
 490
Author: Peter Lawrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-03 10:25:20

Bardzo dobre pytanie. Specyfikacja języka Java potwierdza Twoją sugestię.

Na przykład następujący kod jest poprawny:

short x = 3;
x += 4.6;

I powoduje, że x ma wartość 7, ponieważ jest równoważne:

short x = 3;
x = (short)(x + 4.6);
 259
Author: Thirler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-03 19:11:41

Tak,

W zasadzie kiedy piszemy

i += l; 

Kompilator konwertuje to na

i = (int)(i + l);

Właśnie sprawdziłem .class Kod pliku.

Really a good thing to know

 181
Author: Umesh Awasthi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-28 12:18:52

Musisz rzucić z long do int explicitly w przypadku i = i + l to skompiluje i da poprawne wyjście. jak

i = i + (int)l;

Lub

i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

Ale w przypadku += to po prostu działa dobrze, ponieważ operator domyślnie robi odlewanie typu z typu prawej zmiennej do typu lewej zmiennej, więc nie trzeba rzucać jawnie.

 92
Author: dku.rajkumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-03 10:27:01

Problem polega tutaj na odlewaniu typu.

Po dodaniu int i long,

  1. obiekt int jest rzutowany na long & oba są dodawane i otrzymujesz obiekt long.
  2. ale obiekt long nie może być w domyśle przypisany do int. Więc musisz to zrobić wyraźnie.

Ale += jest zakodowany w taki sposób, że nie powoduje odlewania typu. i=(int)(i+m)

 64
Author: dinesh028,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-03 12:16:17

W Javie konwersje typu są wykonywane automatycznie, gdy typ wyrażenia po prawej stronie operacji przypisania może być bezpiecznie promowany do typu zmiennej po lewej stronie przypisania. W ten sposób możemy bezpiecznie przypisać:

 byte -> short -> int -> long -> float -> double. 

To samo nie zadziała na odwrót. Na przykład nie możemy automatycznie przekonwertować long na int, ponieważ pierwsza wymaga więcej pamięci niż druga i w konsekwencji Informacje mogą zostać utracone. Na siłę takie nawrócenie musimy przeprowadzić wyraźne nawrócenie.
Konwersja Typu

 55
Author: tinker_fairy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-27 05:55:55

Czasami takie pytanie można zadać na rozmowie kwalifikacyjnej.

Na przykład, gdy piszesz:

int a = 2;
long b = 3;
a = a + b;

Nie ma automatycznego typecastingu. W C++ nie będzie żadnego błędu kompilacji powyższego kodu, ale w Javie otrzymasz coś w stylu Incompatible type exception.

Aby tego uniknąć, musisz napisać swój kod w ten sposób:

int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting
 46
Author: Stopfan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-14 21:11:35

Główną różnicą jest to, że z a = a + b, nie ma typecastingu dzieje, więc kompilator dostaje zły na Ciebie za nie typecasting. Ale z a += b, to co tak naprawdę robi to typecasting b do typu zgodnego z a. Więc jeśli zrobisz

int a=5;
long b=10;
a+=b;
System.out.println(a);

To, co naprawdę robisz, to:

int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);
 25
Author: takra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-06 14:16:06

Subtelny punkt tutaj...

Istnieje Typ niejawny dla i+j, gdy j jest podwójnym, a i jest int. Java zawsze zamienia liczbę całkowitą na liczbę podwójną, gdy między nimi występuje operacja.

Aby wyjaśnić i+=j Gdzie i jest liczbą całkowitą, a {[2] } jest liczbą podwójną można opisać jako

i = <int>(<double>i + j)

Zobacz: ten opis odlewania implicit

Możesz wpisać j do (int) W Tym Przypadku dla jasności.

 13
Author: Gabe Nones,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-23 19:12:58

Specyfikacja języka Java Definiuje E1 op= E2 jako odpowiednik E1 = (T) ((E1) op (E2)) Gdzie T jest typem E1 i E1 jest oceniany raz .

To odpowiedź techniczna, ale możesz się zastanawiać, dlaczego tak jest. Cóż, rozważmy następujący program.

public class PlusEquals {
    public static void main(String[] args) {
        byte a = 1;
        byte b = 2;
        a = a + b;
        System.out.println(a);
    }
}

Co ten program drukuje?

Zgadłeś trzy? Szkoda, ten program nie chce się skompilować. Dlaczego? Tak się składa, że dodawanie bajtów w Javie jest zdefiniowane tak, aby zwracać int. To, Wydaje mi się, że to dlatego, że wirtualna maszyna Javy nie definiuje operacji bajtowych do zapisywania na bajtach (jest ich ograniczona liczba, w końcu), użycie operacji integer zamiast tego jest szczegółem implementacji ujawnionym w języku.

Ale jeśli a = a + b nie zadziała, oznacza to, że a += b nigdy nie będzie działać dla bajtów, jeśli E1 += E2 zostanie zdefiniowane jako E1 = E1 + E2. Jak pokazuje poprzedni przykład, tak rzeczywiście byłoby. Jako hack do pracy operatora += dla bajtów i szortów, istnieje ukryta Obsada zaangażowana. To nie jest tak wielki hack, ale w czasie pracy Java 1.0, skupiono się na coraz język wydany na początku. Teraz, ze względu na kompatybilność wsteczną, Ten hack wprowadzony w Javie 1.0 nie mógł zostać usunięty.

 6
Author: Konrad Borowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-25 09:04:37