Final vs Effectively Final u Javi

1. Uvod

Jedna od najzanimljivijih značajki predstavljena u Javi 8 zapravo je konačna. Omogućuje nam da ne napišemo konačni modifikator za varijable, polja i parametre koji se učinkovito tretiraju i koriste poput konačnih.

U ovom uputstvu istražit ćemo ove značajke podrijetla i kako se prema njemu obrađuje kompajler u odnosu na konačni ključna riječ. Nadalje, istražit ćemo rješenje za upotrebu u vezi s problematičnim slučajem učinkovitog korištenja konačnih varijabli.

2. Učinkovito konačno podrijetlo

Jednostavno rečeno, objekti ili primitivne vrijednosti zapravo su konačne ako njihove vrijednosti ne promijenimo nakon inicijalizacije. U slučaju objekata, ako ne promijenimo referencu objekta, tada je ona zapravo konačna - čak i ako dođe do promjene stanja referenciranog objekta.

Prije uvođenja, nismo mogli upotrijebiti lokalnu varijablu koja nije konačna u anonimnoj klasi. Još uvijek ne možemo koristiti varijable kojima je dodijeljeno više od jedne vrijednosti unutar anonimnih klasa, unutarnjih klasa i lambda izraza. Uvođenje ove značajke omogućuje nam da ne moramo koristiti konačni modifikator na varijablama koje su efektivno konačne, štedeći nam nekoliko tipki.

Anonimne klase su unutarnje klase i ne mogu pristupiti ne-konačnim ili ne-efektivno-završnim varijablama ili ih mutirati u svojim obuhvaćajućim opsezima kako je navedeno u JLS 8.1.3. Isto se ograničenje odnosi na lambda izraze, jer pristup može potencijalno stvoriti probleme s istodobnošću.

3. Final vs Effectively Final

Najjednostavniji način da shvatite je li konačna varijabla zapravo konačna jest razmisliti hoće li uklanjanje konačni ključna riječ bi omogućila kodu da se prevede i pokrene:

@FunctionalInterface javno sučelje FunctionalInterface {void testEffectivelyFinal (); zadani void test () {int efektivnoFinalInt = 10; FunctionalInterface funkcionalniInterface = () -> System.out.println ("Vrijednost efektivne varijable je:" + efektivnoFinalInt); }} 

Ponovno dodjeljivanje vrijednosti ili mutiranje gore navedene efektivne konačne varijable učinilo bi kôd nevažećim bez obzira gdje se pojavio.

3.1. Liječenje sastavljača

JLS 4.12.4 kaže da ako uklonimo konačni modifikator iz parametra metode ili lokalne varijable bez uvođenja pogrešaka u vremenu prevođenja, tada je zapravo konačan. Štoviše, ako dodamo konačni ključna riječ deklaraciji varijable u važećem programu, tada je zapravo konačna.

Kompajler Java ne vrši dodatnu optimizaciju za efektivne konačne varijable, za razliku od konačni varijable.

Razmotrimo jednostavan primjer koji deklarira dva završni niz varijable, ali ih koristi samo za spajanje:

javna statička void glavna (String [] args) {final String hello = "hello"; final String world = "svijet"; String test = zdravo + "" + svijet; System.out.println (test); } 

Kompajler bi promijenio kôd izveden u glavni gornja metoda za:

javna statička void glavna (String [] var0) {String var1 = "zdravo svijetu"; System.out.println (var1); }

S druge strane, ako uklonimo konačni modifikatori, varijable bi se učinkovito smatrale konačnima, ali kompajler ih neće ukloniti budući da se koriste samo za spajanje.

4. Atomska modifikacija

Općenito, nije dobra praksa mijenjati varijable korištene u lambda izrazima i anonimnim klasama. Ne možemo znati kako će se ove varijable koristiti u blokovima metoda. Njegova mutacija može dovesti do neočekivanih rezultata u okruženjima s više niti.

Već imamo vodič koji objašnjava najbolje postupke pri korištenju lambda izraza i jedan koji objašnjava uobičajene anti-obrasce kada ih mijenjamo. Ali postoji alternativni pristup koji nam omogućuje modificiranje varijabli u takvim slučajevima koji postiže sigurnost niti pomoću atomskosti.

Paket java.util.concurrent.atomic nudi satove poput AtomicReference i AtomicInteger. Pomoću njih možemo atomski modificirati varijable unutar lambda izraza:

javna statička void glavna (String [] args) {AtomicInteger efektivnoFinalInt = novi AtomicInteger (10); FunctionalInterface funkcijskiInterface = efektivnoFinalInt ::crementAndGet; }

5. Zaključak

U ovom uputstvu saznali smo o najznačajnijim razlikama između konačni i efektivno konačne varijable. Uz to, pružili smo sigurnu alternativu koja nam omogućuje izmjenu varijabli unutar lambda funkcija.