class OuterClass {
...
static class StaticNestedClass {
...
}
class InnerClass {
...
}
}
Bu dahili sınıflara iç içe denir. 2 tipe ayrılırlar:
- Statik olmayan iç içe sınıflar. Bunlara iç sınıflar da denir.
- Statik iç içe sınıflar.
- yerel bir sınıf
- isimsiz bir sınıf

public class Bicycle {
private String model;
private int weight;
public Bicycle(String model, int weight) {
this.model = model;
this.weight = weight;
}
public void start() {
System.out.println("Let's go!");
}
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left!");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
}
İşte sınıfımız var Bicycle
. 2 alanı ve 1 yöntemi vardır: start()
. 
Handlebar
ve Seat
. Kodları sınıfın içinde yazılır Bicycle
. Bunlar tam teşekküllü sınıflardır: görebileceğiniz gibi, her birinin kendi yöntemleri vardır. Bu noktada, bir sorunuz olabilir: neden bir sınıfı diğerinin içine koyalım? Neden onları iç sınıflar yapalım? Peki, programımızda gidon ve koltuk kavramları için ayrı sınıflara ihtiyacımız olduğunu varsayalım. Bunları iç içe yapmamıza gerek yok elbette! Sıradan sınıflar yapabiliriz. Örneğin, bunun gibi:
public class Handlebar {
public void right() {
System.out.println("Steer right!");
}
public void left() {
System.out.println("Steer left");
}
}
public class Seat {
public void up() {
System.out.println("Seat up!");
}
public void down() {
System.out.println("Seat down!");
}
}
Çok iyi soru! Elbette teknoloji ile sınırlı değiliz. Bunu yapmak kesinlikle bir seçenektir. Burada önemli olan, derslerin belirli bir program ve amacı açısından doğru tasarlanmasıdır. İç sınıflar, başka bir varlığa ayrılmaz bir şekilde bağlı olan bir varlığı ayırmak içindir. Gidon, koltuklar ve pedallar bir bisikletin bileşenleridir. Bisikletten ayrı, pek bir anlam ifade etmiyorlar. Tüm bu kavramları ayrı ortak sınıflar yapsaydık, programımızda şöyle bir kod olurdu:
public class Main {
public static void main(String[] args) {
Handlebar handlebar = new Handlebar();
handlebar.right();
}
}
Hmm... Bu kodun anlamını açıklamak bile zor. Biraz belirsiz gidonumuz var (Neden gerekli? Dürüst olmak gerekirse hiçbir fikrim yok). Ve bu kol sağa dönüyor... kendi kendine, bisikletsiz... nedense. Gidon kavramını bisiklet kavramından ayırarak programımızda biraz mantık kaybettik. Bir iç sınıf kullanıldığında kod çok farklı görünür:
public class Main {
public static void main(String[] args) {
Bicycle peugeot = new Bicycle("Peugeot", 120);
Bicycle.Handlebar handlebar = peugeot.new Handlebar();
Bicycle.Seat seat = peugeot.new Seat();
seat.up();
peugeot.start();
handlebar.left();
handlebar.right();
}
}
Konsol çıktısı:
Seat up!
Let's go!
Steer left!
Steer right!
Şimdi gördüklerimiz aniden mantıklı geliyor! :) Bir bisiklet nesnesi oluşturduk. İki bisiklet "alt nesnesi" oluşturduk — bir gidon ve bir sele. Koltuğu konfor için yükselttik ve yola çıktık: gerektiği gibi pedal çevirin ve direksiyonu çevirin! :) İhtiyacımız olan yöntemler uygun nesneler üzerinde çağrılır. Hepsi basit ve kullanışlı. Bu örnekte gidonu ve seleyi ayırmak kapsüllemeyi geliştiriyor (bisiklet parçalarıyla ilgili verileri ilgili sınıf içinde saklıyoruz) ve daha detaylı bir soyutlama oluşturmamızı sağlıyor. Şimdi farklı bir duruma bakalım. Bir bisikletçiyi ve bisiklet yedek parçalarını simüle eden bir program oluşturmak istediğimizi varsayalım. 
-
Bir iç sınıfın nesnesi, bir dış sınıfın nesnesi olmadan var olamaz.
Seat
Bu mantıklı: bu nedenle programımızda ve iç sınıfları oluşturdukHandlebar
— böylece artık gidon ve koltuklarla yetinmeyiz.Bu kod derlenmiyor:
public static void main(String[] args) { Handlebar handlebar = new Handlebar(); }
Bir diğer önemli özellik bundan kaynaklanmaktadır:
-
Bir iç sınıfın nesnesi, dış sınıfın değişkenlerine erişebilir.
int seatPostDiameter
Örneğin sınıfımıza (koltuk direğinin çapını temsil eden) bir değişken ekleyelimBicycle
.Ardından , iç sınıfta koltuk özelliklerini görüntüleyen
Seat
bir yöntem oluşturabiliriz :displaySeatProperties()
public class Bicycle { private String model; private int weight; private int seatPostDiameter; public Bicycle(String model, int weight, int seatPostDiameter) { this.model = model; this.weight = weight; this.seatPostDiameter = seatPostDiameter; } public void start() { System.out.println("Let's go!"); } public class Seat { public void up() { System.out.println("Seat up!"); } public void down() { System.out.println("Seat down!"); } public void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
Ve şimdi bu bilgiyi programımızda görüntüleyebiliriz:
public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); Bicycle.Seat seat = bicycle.new Seat(); seat.displaySeatProperties(); } }
Konsol çıktısı:
Seat properties: seatpost diameter = 40
Not:yeni değişken, en katı erişim değiştiricisiyle ( ) bildirilir
private
. Ve yine de iç sınıfın erişimi var! -
Bir iç sınıfın nesnesi, bir dış sınıfın statik yönteminde yaratılamaz.
Bu, iç sınıfların nasıl düzenlendiğine ilişkin belirli özelliklerle açıklanır. Bir iç sınıf, parametrelere sahip kuruculara veya yalnızca varsayılan kurucuya sahip olabilir. Ancak ne olursa olsun, bir iç sınıfın nesnesini oluşturduğumuzda, dış sınıfın nesnesine yapılan bir başvuru, iç sınıfın yaratılan nesnesine görünmez bir şekilde iletilir. Sonuçta, böyle bir nesne referansının varlığı mutlak bir gerekliliktir. Aksi takdirde, iç sınıfın nesnelerini oluşturamayız.
Ancak, dış sınıfın bir yöntemi statik ise, o zaman dış sınıfın bir nesnesine sahip olmayabiliriz! Ve bu, bir iç sınıfın nasıl çalıştığına dair mantığın ihlali olur. Bu durumda derleyici bir hata üretecektir:
public static Seat createSeat() { // Bicycle.this cannot be referenced from a static context return new Seat(); }
-
Bir iç sınıf, statik değişkenler ve yöntemler içeremez.
Mantık aynıdır: statik yöntemler ve değişkenler var olabilir ve bir nesnenin yokluğunda bile çağrılabilir veya bunlara başvurulabilir.
Ancak dış sınıftan bir nesne olmadan iç sınıfa erişimimiz olmaz.
Açık bir çelişki! Bu nedenle iç sınıflarda statik değişkenlere ve yöntemlere izin verilmez.
Bunları oluşturmaya çalışırsanız derleyici bir hata üretecektir:
public class Bicycle { private int weight; public class Seat { // An inner class cannot have static declarations public static void displaySeatProperties() { System.out.println("Seat properties: seatpost diameter = " + Bicycle.this.seatPostDiameter); } } }
-
Bir iç sınıfın nesnesini oluştururken erişim değiştiricisi önemlidir.
Bir iç sınıf, standart erişim değiştiricileri ile işaretlenebilir:
public
,private
,protected
vepackage private
.Bu neden önemli?
Bu, programımızda iç sınıfın örneklerini nerede oluşturabileceğimizi etkiler.
Sınıfımız
Seat
olarak bildirilirse , başka herhangi bir sınıfta nesnelerpublic
oluşturabiliriz .Seat
Tek gereksinim, dış sınıftan bir nesnenin de var olması gerektiğidir.Bu arada, bunu zaten burada yaptık:
public class Main { public static void main(String[] args) { Bicycle peugeot = new Bicycle("Peugeot", 120); Bicycle.Handlebar handlebar = peugeot.new Handlebar(); Bicycle.Seat seat = peugeot.new Seat(); seat.up(); peugeot.start(); handlebar.left(); handlebar.right(); } }
Handlebar
Sınıftan iç sınıfa kolayca erişim sağladıkMain
.İç sınıfı olarak bildirirsek
private
, sadece dış sınıf içinde nesneler oluşturabileceğiz.Seat
Artık "dışarıdan" bir nesne oluşturamayız :private class Seat { // Methods } public class Main { public static void main(String[] args) { Bicycle bicycle = new Bicycle("Peugeot", 120, 40); // Bicycle.Seat has private access in Bicycle Bicycle.Seat seat = bicycle.new Seat(); } }
Muhtemelen mantığı zaten anlamışsınızdır :)
-
İç sınıflar için erişim değiştiricileri, sıradan değişkenlerle aynı şekilde çalışır.
Değiştirici
protected
, aynı paketteki alt sınıflardaki ve sınıflardaki bir örnek değişkene erişim sağlar.protected
ayrıca iç sınıflar için de çalışır.protected
İç sınıfın nesnelerini oluşturabiliriz :- dış sınıfta;
- alt sınıflarında;
- aynı paketteki sınıflarda.
İç sınıfın bir erişim değiştiricisi ( ) yoksa
package private
, iç sınıfın nesneleri oluşturulabilir:- dış sınıfta;
- aynı paketteki sınıflarda.
Değiştiricilere uzun süredir aşinasınız, bu yüzden burada sorun yok.
GO TO FULL VERSION