Végső vs hatékonyan Java-ban végleges

1. Bemutatkozás

A Java 8 egyik legérdekesebb szolgáltatása végleges. Ez lehetővé teszi számunkra, hogy ne írjuk a végső módosító változókhoz, mezőkhöz és paraméterekhez, amelyeket hatékonyan kezelnek és használnak, mint a véglegeseket.

Ebben az oktatóanyagban megvizsgáljuk ezt a funkciót eredetét és azt, hogy a fordító hogyan kezeli a végső kulcsszó. Ezenkívül megvizsgáljuk a hatékony végső változók problémás felhasználási esetére vonatkozó megoldást.

2. Hatékony eredet

Egyszerűen, az objektumok vagy a primitív értékek akkor véglegesek, ha az inicializálás után nem változtatunk az értékein. Objektumok esetében, ha nem változtatunk egy objektum referenciáján, akkor az ténylegesen végleges - még akkor is, ha változás történik a hivatkozott objektum állapotában.

Bevezetése előtt nem használhatunk egy nem végleges helyi változót egy névtelen osztályban. Továbbra sem használhatunk olyan változókat, amelyekhez egynél több érték van hozzárendelve anonim osztályok, belső osztályok és lambda kifejezések belsejében. Ennek a szolgáltatásnak a bevezetése lehetővé teszi számunkra, hogy ne kelljen a végső módosító a gyakorlatilag végleges változókon, megtakarítva nekünk néhány billentyűleütést.

Az anonim osztályok belső osztályok, és nem férhetnek hozzá a nem végső vagy nem hatékonyan végleges változókhoz, és nem mutálhatják őket a JLS 8.1.3. Ugyanez a korlátozás vonatkozik a lambda kifejezésekre is, mivel a hozzáférés potenciálisan egyidejűségi problémákat okozhat.

3. Döntő vs hatékonyan Végleges

A legegyszerűbb módja annak megértésének, hogy egy végső változó ténylegesen végleges-e, az a gondolkodás, hogy eltávolítja-e a végső kulcsszó lehetővé tenné a kód fordítását és futtatását:

@FunctionalInterface nyilvános felület FunctionalInterface {void testEffectivelyFinal (); alapértelmezett void teszt () {int hatékonyanFinalInt = 10; FunctionalInterface funkcionálisInterface = () -> System.out.println ("A hatékony változó értéke:" + effectiveFinalInt); }} 

Egy érték újbóli hozzárendelése vagy a fentiek tényleges végső változójának mutálása a kódot érvénytelenné tenné, függetlenül attól, hogy hol fordul elő.

3.1. Compiler kezelés

A JLS 4.12.4 kimondja, hogy ha eltávolítjuk a végső módosító egy metódusparaméterből vagy egy helyi változóból fordítási időbeli hibák bevezetése nélkül, akkor gyakorlatilag végleges. Sőt, ha hozzáadjuk a végső kulcsszó egy változó deklarációjához egy érvényes programban, akkor gyakorlatilag végleges.

A Java fordító nem végez további optimalizálást a végleges változók hatékonyabbá tételéhez, ellentétben azokkal végső változók.

Vegyünk egy egyszerű példát, amely kettőt deklarál utolsó húr változók, de csak összefűzésre használják őket:

public static void main (String [] args) {final String hello = "hello"; végső vonós világ = "világ"; Karakterteszt = szia + "" + világ; System.out.println (teszt); } 

A fordító megváltoztatná a fő- a fenti módszer:

public static void main (String [] var0) {String var1 = "szia világ"; System.out.println (var1); }

Másrészről, ha eltávolítjuk a végső módosítók, a változókat ténylegesen véglegesnek tekintenék, de a fordító nem távolítja el őket mivel csak összefűzésre használják őket.

4. Atommódosítás

Általában, nem jó gyakorlat a lambda kifejezésekben és az anonim osztályokban használt változók módosítása. Nem tudhatjuk, hogy ezeket a változókat hogyan fogják használni a módszerblokkokon belül. Mutációjuk váratlan eredményekhez vezethet többszálas környezetben.

Már van egy bemutatónk, amely elmagyarázza a lambda kifejezések használatának legjobb gyakorlatait, és egy másik, amely elmagyarázza a szokásos anti-mintákat, amikor módosítjuk őket. De létezik egy alternatív megközelítés, amely lehetővé teszi számunkra a változók módosítását ilyen esetekben, és az atomitás révén eléri a menetbiztonságot.

A csomag java.util.concurrent.atomic olyan osztályokat kínál, mint AtomicReference és AtomicInteger. Használhatjuk őket a lambda kifejezéseken belüli változók atomi módosítására:

public static void main (String [] args) {AtomicInteger hatékonyanFinalInt = új AtomicInteger (10); FunctionalInterface funkcionálisInterface = hatékonyanFinalInt :: inkrementAndGet; }

5. Következtetés

Ebben az oktatóanyagban megismerhettük a legfontosabb különbségeket végső és hatékonyan a végső változókat. Ezenkívül biztosítottunk egy biztonságos alternatívát, amely lehetővé teszi a lambda függvényekben lévő változók módosítását.