Anonim sınıflarla, aslında "isimsiz" iç içe bir sınıf bildiriyorsunuz. İç içe sınıflar için, derleyici, bağımsız değişken olarak kullandığı tüm değişkenleri alacak bir yapıcı ile yeni bir bağımsız ortak sınıf oluşturur ("adlandırılmış" iç içe sınıflar için, bu her zaman orijinal / çevreleyen sınıfın bir örneğidir). Bu, çalışma zamanı ortamının iç içe sınıf kavramına sahip olmaması nedeniyle yapılır, bu nedenle iç içe geçmişten bağımsız bir sınıfa (otomatik) dönüştürme yapılması gerekir.
Örneğin bu kodu ele alalım:
public class EnclosingClass {
public void someMethod() {
String shared = "hello";
new Thread() {
public void run() {
// this is not valid, won't compile
System.out.println(shared); // this instance expects shared to point to the reference where the String object "hello" lives in heap
}
}.start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
}
Bu işe yaramaz, çünkü derleyicinin kaputun altında yaptığı şey budur:
public void someMethod() {
String shared = "hello";
new EnclosingClass$1(shared).start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
Orijinal anonim sınıfın yerini, derleyicinin oluşturduğu bazı bağımsız sınıflar alır (kod tam değildir, ancak size iyi bir fikir vermelidir):
public class EnclosingClass$1 extends Thread {
String shared;
public EnclosingClass$1(String shared) {
this.shared = shared;
}
public void run() {
System.out.println(shared);
}
}
Gördüğünüz gibi, bağımsız sınıf paylaşılan nesneye bir referans tutar, java'daki her şeyin pass-by olduğunu unutmayın, bu nedenle EnclosingClass içindeki 'paylaşılan' referans değişkeni değişse bile, işaret ettiği örnek değiştirilmez ve ona işaret eden diğer tüm referans değişkenleri (anonim sınıftaki gibi: 1 TL'yi çevreleyen) bunun farkında olmayacaktır. Bu, derleyicinin sizi bu 'paylaşılan' değişkenleri nihai olarak bildirmeye zorlamasının ana nedenidir, böylece bu tür davranışlar zaten çalışan kodunuza girmez.
Şimdi, anonim bir sınıfın içinde bir örnek değişkeni kullandığınızda olan budur (sorununuzu çözmek, mantığınızı bir "örnek" yöntemine veya bir sınıfın yapıcısına taşımak için yapmanız gereken budur):
public class EnclosingClass {
String shared = "hello";
public void someMethod() {
new Thread() {
public void run() {
System.out.println(shared); // this is perfectly valid
}
}.start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
}
Derleyici kodu değiştireceğinden, bu derlenir, çünkü yeni oluşturulan 1 $ Enclosing sınıfı, EnclosingClass örneğinin somutlaştırıldığı örneğe bir referans tutacaktır (bu yalnızca bir temsildir, ancak gitmenizi sağlayacaktır):
public void someMethod() {
new EnclosingClass$1(this).start();
// change the reference 'shared' points to, with a new value
shared = "other hello";
System.out.println(shared);
}
public class EnclosingClass$1 extends Thread {
EnclosingClass enclosing;
public EnclosingClass$1(EnclosingClass enclosing) {
this.enclosing = enclosing;
}
public void run() {
System.out.println(enclosing.shared);
}
}
Bunun gibi, EnclosingClass içindeki 'paylaşılan' referans değişkeni yeniden atandığında ve bu, Thread # run () çağrısından önce gerçekleştiğinde, iki kez yazdırılan "diğer merhaba" ifadesini görürsünüz, çünkü şimdi EnclosingClass $ 1 # çevreleyen değişken referans tutacaktır sınıfın bildirildiği nesneye bağlandığından, bu nesnedeki herhangi bir öznitelikte yapılan değişiklikler EnclosingClass $ 1 örnekleri tarafından görülebilir.
Konu hakkında daha fazla bilgi için, bu mükemmel blog gönderisini görebilirsiniz (benim tarafımdan yazılmamış): http://kevinboone.net/java_inner.html