a += b vs a = a + b v Javě

Martin Simbartl | 12. 1. 2008 | Software | | Přečteno: 4,009

Často se setkávám s tvrzením, že v Javě přiřazení a += b je to samé jako a = a + b. Také si to myslíte? Ano? Jste si tím skutečně jisti?

Pokud jste si tím opravdu tak jisti, jak byste vysvětlili následující věc? Mějme jednoduchý kousek kódu

1
2
3
4
5
6
7
8
9
// CompoundAssignmentTest.java
class CompoundAssignmentTest {
    public static void main(String[] args) {
        int a = 1;
        float b = 2.0f;
        a += b;
        a = a + b;
    }
}

a zkusme ho zkompilovat.

> javac -version
javac 1.6.0_03
> javac CompoundAssignmentTest.java
CompoundAssignmentTest.java:7: possible loss of precision
found   : float
required: int
        a = a + b;
              ^
1 error

Hmm. Nejde. Podíváme-li se pozorně, vidíme, že chyba nastala až na řádce 7, tedy na řádce obsahující kód a = a + b;. Zakomentujeme-li řádek 7 a zkusíme kód zkompilovat znovu, vše je úspěšně zkompilováno. Pokud jsou přiřazení a += b a a = a + b stejná, jak je možné, že složené přiřazení a += b jde zkompilovat a přiřazení a = a + b nejde?

Odpověď je celkem jednoduchá. Podívejme se do The Java Language Specification, 3rd Edition. První odstavec kapitoli 15.26.2 Compound Assignment Operators říká:

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

Aha! Implicitní přetypování! Naše řádka 6 a += b; je tedy převedena na a = (int)(a + b);. Na řádce 7 a = a + b; implicitní koverze na int není. Proto jsme dostali chybu při kompilaci. Na tuto vlastnost složeného přiřazení bychom si měli dávat pozor. V našem případě je proměnná a typu int a proměnná b typu float. Při vyhodnocování výrazu (a + b) je hodnota proměnné a povýšena na typ float a je sečtena s hodnotou proměnné b. Výsledná hodnota je typu float. Až sem je vše v pořádku. Nyní však dojde k implicitní konverzi hodnoty typu float na typ int a její následné přiřazení do proměnné a. Této konverzi se říká Narrowing Primitive Conversion a může při ní dojít ke ztrátě dat. Tuto implicitní konverzi u složeného přiřazení za nás udělal kompilátor tím, že vygeneroval odpovídající instrukce Java bajt kódu.

Pořád si myslíte, že a += b a a = a + b je v Javě to samé?

Sdílení:
  • Facebook
  • Google Bookmarks
  • Linkuj.cz

Komentáře

Komentář od ufak
Datum: 17. 1. 2008, 12:04

To teda neni hezke. Mel by dat take warning.
Dobry postreh!

Komentář od Ladislav Thon
Datum: 17. 1. 2008, 12:40

Ech, takových záludností v Javě je, doporučuju knížku http://www.javapuzzlers.com/ :-)

Komentář od trk
Datum: 20. 1. 2008, 14:09

Mne to teda jako zaludnost nepripada. Jenze ja mam tu vyhodu, ze jsem se Javu neucil na stredni/vysoke skole scitanim matic, ale poradne :)