Razgovor o Java unutrašnjim klasama: unutrašnje klase članice, lokalne unutrašnje klase, anonimne unutrašnje klase, statičke unutrašnje klase
U Javi se jedna klasa može definisati unutar druge klase ili unutar metode; takva klasa se naziva unutrašnjom klasom. Uopšteno, unutrašnje klase se dele na unutrašnje klase članice, lokalne unutrašnje klase, anonimne unutrašnje klase i statičke unutrašnje klase.
1) Unutrašnja klasa članica
Unutrašnja klasa članica je najčešća unutrašnja klasa, pogledajte sledeći kod:
class Wanger {
int age = 18;
class Wangxiaoer {
int age = 81;
}
}Izgleda kao da unutrašnja klasa Wangxiaoer predstavlja jednog člana klase Wanger. Unutrašnja klasa članica može neograničeno da pristupa svim članima i poljima spoljašnje klase.
public class Wanger {
int age = 18;
private String name = "Chenmo Wang Er";
static double money = 1;
class Wangxiaoer {
int age = 81;
public void print() {
System.out.println(name);
System.out.println(money);
}
}
}Unutrašnja klasa može slobodno da pristupa članovima spoljašnje klase, ali obrnuto — kada spoljašnja klasa želi da pristupi članovima unutrašnje klase — nije tako lako. Mora prvo da kreira objekat unutrašnje klase članice, a zatim preko tog objekta pristupa:
public class Wanger {
int age = 18;
private String name = "Chenmo Wang Er";
static double money = 1;
public Wanger () {
new Wangxiaoer().print();
}
class Wangxiaoer {
int age = 81;
public void print() {
System.out.println(name);
System.out.println(money);
}
}
}To znači da, kada želimo iz statičke metode da pristupimo unutrašnjoj klasi članici, moramo prvo da kreiramo objekat spoljašnje klase, jer unutrašnja klasa zavisi od spoljašnje klase.
public class Wanger {
int age = 18;
private String name = "Chenmo Wang Er";
static double money = 1;
public Wanger () {
new Wangxiaoer().print();
}
public static void main(String[] args) {
Wanger wanger = new Wanger();
Wangxiaoer xiaoer = wanger.new Wangxiaoer();
xiaoer.print();
}
class Wangxiaoer {
int age = 81;
public void print() {
System.out.println(name);
System.out.println(money);
}
}
}Ovakav način kreiranja unutrašnje klase se u praksi retko koristi, jer su unutrašnja i spoljašnja klasa čvrsto povezane, što otežava upotrebu.
2) Lokalna unutrašnja klasa
Lokalna unutrašnja klasa je klasa definisana unutar metode ili unutar nekog opsega važenja, pa je životni vek lokalne unutrašnje klase ograničen na taj opseg.
public class Wangsan {
public Wangsan print() {
class Wangxiaosan extends Wangsan{
private int age = 18;
}
return new Wangxiaosan();
}
}Lokalna unutrašnja klasa je poput lokalne promenljive — ne mogu je modifikovati modifikatori prava pristupa, kao što su public, protected, private i static.

3) Anonimna unutrašnja klasa
Anonimna unutrašnja klasa je vrsta koju najčešće koristimo, posebno pri pokretanju više niti — često se koristi, a IDE je može generisati automatski.
public class ThreadDemo {
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
t.start();
}
}Anonimna unutrašnja klasa je kao argument metode — po upotrebi nestaje, pa ne moramo za nju posebno da pišemo konstruktor; njeno ime sistem automatski dodeljuje. Pažljivijim posmatranjem bajtkoda posle kompiliranja može se uočiti da anonimna unutrašnja klasa čak nije dostojna ni imena — haha — jednostavno pozajmi ime spoljašnje klase pa se sve reši sa $1.

Anonimna unutrašnja klasa jedina je vrsta klase bez konstruktora. Za gorenavedeni zapis važi i to da nam anonimna unutrašnja klasa ne dozvoljava da za nju pišemo konstruktor, jer je u pitanju nešto poput objekta neposredno kreiranog ključnom reči new.
Uloga anonimne unutrašnje klase je uglavnom da nasledi druge klase ili implementira interfejse, bez potrebe za dodavanjem dodatnih metoda, što olakšava implementiranje ili prepisivanje nasleđenih metoda.
4) Statička unutrašnja klasa
Statička unutrašnja klasa je slična unutrašnjoj klasi članici, samo je dodatno modifikovana ključnom reči static.
public class Wangsi {
static int age;
double money;
static class Wangxxiaosi {
public Wangxxiaosi (){
System.out.println(age);
}
}
}Zbog prisustva ključne reči static, statička unutrašnja klasa ne sme da pristupa nestatičkim promenljivama i metodama spoljašnje klase — što je vrlo lako razumeti: zašto bi statička unutrašnja klasa pristupala mojim nestatičkim poljima?

Zašto uopšte koristiti unutrašnje klase? To je vrlo dobro pitanje — vreme je za pozivanje na autoritete.
U knjizi „Thinking in Java“ stoji sledeće:
Najprivlačniji razlog za upotrebu unutrašnjih klasa jeste što svaka unutrašnja klasa može nezavisno da nasledi jednu (interfejsku) implementaciju, tako da nije od uticaja to što spoljašnja klasa možda već nasleđuje neku (interfejsku) implementaciju.
U dizajnu programa ponekad postoje problemi koje je teško rešiti isključivo interfejsima; tada možemo iskoristiti sposobnost unutrašnjih klasa da nasleđuju više konkretnih ili apstraktnih klasa i tako rešimo te probleme u dizajnu. Može se reći da interfejsi rešavaju samo deo problema, dok unutrašnje klade rešenje višestrukog nasleđivanja čine potpunijim.
Korišćenje unutrašnjih klasa donosi i sledeće osobine:
- Unutrašnja klasa može imati više instanci, od kojih svaka ima sopstvene informacije o stanju, međusobno nezavisne od ostalih spoljašnjih objekata.
- Unutar jedne spoljašnje klase, više unutrašnjih klasa može na različite načine implementirati isti interfejs ili naslediti istu klasu.
- Trenutak kreiranja objekta unutrašnje klase ne zavisi od kreiranja objekta spoljašnje klase.
- Unutrašnja klasa nema zbunjujući odnos „je-nešto“ (is-a) — ona je samostalan entitet.
- Unutrašnja klasa pruža bolju enkapsulaciju — osim te spoljašnje klase, nijedna druga klasa ne može joj pristupiti.
Referentni link: https://www.cnblogs.com/dolphin0520/p/3811445.html, autor: Matrix Hai Zi, obradio: Chenmo Wang Er
