Java iç sınıfı ve statik iç içe sınıf


1766

Java'da bir iç sınıf ile statik bir iç içe sınıf arasındaki temel fark nedir? Tasarım / uygulama bunlardan birini seçmede rol oynuyor mu?


65
Joshua Bloch'un cevabı Etkili Java okumasında item 22 : Favor static member classes over non static
Raymond Chenon

4
Kayıt için, aynı kitabın 3. baskısında 24. madde.
ZeroCool

Yanıtlar:


1696

Gönderen Java Eğitimi :

İç içe sınıflar iki kategoriye ayrılır: statik ve statik olmayan. Statik olarak bildirilen iç içe sınıflara basitçe statik iç içe sınıflar denir. Statik olmayan iç içe sınıflara iç sınıf denir.

Statik iç içe sınıflara ekteki sınıf adı kullanılarak erişilir:

OuterClass.StaticNestedClass

Örneğin, statik iç içe sınıf için bir nesne oluşturmak için şu sözdizimini kullanın:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

İç sınıfın örnekleri olan nesneler, dış sınıfın bir örneğinde bulunur. Aşağıdaki sınıfları düşünün:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

InnerClass'ın bir örneği yalnızca OuterClass'ın bir örneğinde bulunabilir ve içine alan örneğinin yöntemlerine ve alanlarına doğrudan erişebilir.

Bir iç sınıfı somutlaştırmak için önce dış sınıfı somutlaştırmalısınız. Ardından, bu sözdizimiyle dış nesnenin içindeki iç nesneyi oluşturun:

OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

bkz. Java Eğitimi - İç İçe Sınıflar

Tamlık için, ek bir örneği olmayan bir iç sınıf diye bir şey olduğunu unutmayın :

class A {
  int t() { return 1; }
  static A a =  new A() { int t() { return 2; } };
}

Burada, statik bir bağlamda tanımlanannew A() { ... } bir iç sınıftır ve içine alan bir örneği yoktur.


130
Aynı zamanda doğrudan statik iç içe sınıfını içe ki Zihin, siz (dosyanın üst kısmında) yapabilirdi yani: import OuterClass.StaticNestedClass; o zaman sınıfına atıfta sadece OuterClass olarak.
Camilo Díaz Repka

4
@Martin, bu bir iç sınıf yaratma deyiminin özel bir teknik adı var OuterClass.InnerClass innerObject = outerObject.new InnerClass();mı?
Geek

7
Peki, özel statik iç içe sınıfın kullanımı nedir? OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass () gibi dışarıdan başlatamadığımızı düşünüyorum.
RoboAlex

1
@Ilya Kogan: Demek istediğim, ebeveynin sınıf alanlarına statik veya statik olmayan (alt sınıf statik olmayan bir sınıfsa) erişebileceğimizi biliyorum, özelliklerini birkaç kez kullandım, ama ne tür bir bellek modeli olduğunu merak ediyordum onlar takip eder? kavramları onları ayrı bir kavram olarak kapsıyor mu? OOP içinde gerçekten uygun oldukları yerde değilse. Bana bir arkadaş sınıfı gibi görünüyor :)
Mubashar

4
@martin, bu konuya inanılmaz derecede geç geldiğimi biliyorum ama: Bu sizin değişkeniniz, a, sınıfın statik bir alanı, A. 'new A () tarafından oluşturulan anonim sınıf anlamına gelmez {int t () {dönüş 2; }} ', statik alana basitçe başka bir nesne atamamdan daha statiktir: a, aşağıdaki gibi: class B {static void main (string s) {Aa = new A ()}} (A & B aynı Bu A'yı statik bir sınıf yapmaz. Bağlandığınız iş parçacığında belirtilen referanstaki "statik bağlam" ifadesi inanılmaz derecede belirsizdir. Aslında, bu konudaki yorumların çoğunda bu kaydedildi.
GrantRobertson

599

Java öğretici diyor :

Terminoloji: İç içe sınıflar iki kategoriye ayrılır: statik ve statik olmayan. Statik olarak bildirilen iç içe sınıflara basitçe statik iç içe sınıflar denir. Statik olmayan iç içe sınıflara iç sınıf denir.

Genel olarak, "iç içe" ve "iç" terimleri çoğu programcı tarafından birbirinin yerine kullanılır, ancak hem iç hem de statiki kapsayan doğru "iç içe sınıf" terimini kullanacağım.

Sınıflar iç içe geçmiş ve sonsuz olabilir sınıfı D, vs içeren C sınıfı içeren sınıf B içerebilir, örneğin sınıf A genel olarak kötü bir tasarım Ancak, sınıf iç içe geçme fazla bir seviye, çok nadirdir.

Yuvalanmış bir sınıf oluşturmanın üç nedeni vardır:

  • organizasyon: bazen bir sınıfı başka bir sınıfın ad alanına ayırmak en mantıklı görünmektedir, özellikle de başka bir bağlamda kullanılmayacaksa
  • erişim: iç içe sınıflar, içerdiği sınıfların değişkenlerine / alanlarına özel erişime sahiptir (tam olarak hangi değişkenler / alanlar iç veya statik olsun iç içe sınıfın türüne bağlıdır).
  • kolaylık: her yeni tür için yeni bir dosya oluşturmak zorunda kalmak, özellikle tür yalnızca bir bağlamda kullanılacaksa, rahatsız edicidir.

Orada Java iç içe sınıfın dört çeşit . Kısacası, bunlar:

  • static class : başka bir sınıfın statik üyesi olarak bildirildi
  • iç sınıf : başka bir sınıfın örnek üyesi olarak bildirildi
  • yerel iç sınıf : başka bir sınıfın örnek yöntemi içinde bildirildi
  • anonim iç sınıf : yerel bir iç sınıf gibi, ancak bir kerelik bir nesne döndüren bir ifade olarak yazılır

Daha ayrıntılı olarak açıklayayım.


Statik Sınıflar

Statik sınıflar anlaşılması en kolay türdür çünkü kapsayıcı sınıfın örnekleri ile ilgisi yoktur.

Statik sınıf, başka bir sınıfın statik üyesi olarak bildirilen bir sınıftır. Tıpkı diğer statik bireyleri gibi böyle bir sınıf kendi ad olarak içeren sınıf bu kullanımları hakkında sadece bir askı gerçekten örneğin sınıf Keçi sınıf statik üyesi olarak ilan Rhino paketi içinde , pizza adıyla bilinir pizza.Rhino.Goat .

package pizza;

public class Rhino {

    ...

    public static class Goat {
        ...
    }
}

Açıkçası, statik sınıflar oldukça değersiz bir özelliktir çünkü sınıflar zaten paketlere göre ad alanlarına ayrılmıştır. Statik bir sınıf oluşturmanın akla gelebilecek tek nedeni, böyle bir sınıfın kendi sınıfının özel statik üyelerine erişimi olmasıdır, ancak bunu statik sınıf özelliğinin var olması için oldukça topal bir gerekçe olarak buluyorum.


İç Sınıflar

İç sınıf, başka bir sınıfın statik olmayan bir üyesi olarak bildirilen bir sınıftır:

package pizza;

public class Rhino {

    public class Goat {
        ...
    }

    private void jerry() {
        Goat g = new Goat();
    }
}

Statik bir sınıfta olduğu gibi, iç sınıf, içerdiği sınıf adı olan pizza.Rhino.Goat tarafından nitelendirilmiş olarak bilinir , ancak içeren sınıfın içinde, basit adıyla bilinir. Bununla birlikte, bir iç sınıfın her örneği, içeren sınıf belirli bir örneği ilişkilidir: Yukarıda, keçi oluşturulan Jerry , dolaylı olarak bağlıdır Rhino örneği bu olarak Jerry . Aksi takdirde, Keçi'yi somutlaştırdığımızda ilişkili Rhino örneğini açık hale getiririz :

Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();

(İç türe , garip yeni sözdiziminde yalnızca Keçi olarak bahsettiğinize dikkat edin : Java, içerdiği türü gergedan kısmından alır. Ve evet, yeni rhino.Goat () benim için de daha anlamlı olurdu.)

Peki bu bize ne kazandırıyor? İç sınıf örneği, içeren sınıf örneğinin örnek üyelerine erişime sahiptir. Bu parça, örneğin üye bir iç sınıf içinde ifade edilir ile , sadece, basit isimler değil ile bu ( bu iç sınıf iç sınıfı örneği değil, ilişkili içeren sınıf örneği belirtir):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

İç sınıfında, sen başvurabilirsiniz bu kadar içeren sınıfın Rhino.this , ve kullanabileceğiniz bu üyelerinin, başvurmak için örneğin Rhino.this.barry .


Yerel İç Sınıflar

Yerel bir iç sınıf, bir yöntemin gövdesinde bildirilen bir sınıftır. Böyle bir sınıf yalnızca içerme yöntemi içinde bilinir, bu nedenle yalnızca somutlaştırılabilir ve üyelerine içerme yöntemi içinde erişebilir. Kazanç, yerel bir iç sınıf örneğinin bağlama yönteminin nihai yerel değişkenlerine bağlı olması ve bunlara erişebilmesidir. Örnek, içerdiği yöntemin bir son yerelini kullandığında, değişken, kapsam dışına çıkmış olsa bile, değişken, oluşturma sırasında tuttuğu değeri korur (bu, Java'nın kaba, sınırlı kapanma sürümüdür).

Yerel bir iç sınıf, bir sınıfın veya paketin üyesi olmadığından, bir erişim düzeyi ile bildirilmez. (Ancak, kendi üyelerinin normal bir sınıftaki gibi erişim seviyelerine sahip oldukları açık olmalıdır.)

Yerel bir iç sınıf bir örnek yöntemi beyan edilirse, iç sınıfının bir örneğinin içeren yöntem en düzenlediği örneğine bağlıdır bu örneğinin oluşturulduğu sırada ve böylece içeren sınıfının örneği üyeleri bir örneği olduğu gibi erişilebilir iç sınıf. Yerel bir iç sınıfı basitçe örneği aracılığıyla Adından, örneğin yerel iç sınıf Kedi olarak örneği yeni Cat () Tahmin edebileceğiniz gibi, değil yeni this.Cat ().


Anonim İç Sınıflar

İsimsiz bir iç sınıf, yerel bir iç sınıf yazmanın sözdizimsel olarak uygun bir yoludur. En yaygın olarak, bir yerel iç sınıf, içerme yöntemi her çalıştırıldığında en fazla bir kez başlatılır. Yerel iç sınıf tanımını ve tek somutlaştırmasını tek bir uygun sözdizimi biçiminde birleştirebilseydik iyi olurdu ve sınıf için bir isim düşünmek zorunda kalmazsak da güzel olurdu (daha az yararsızdır) kodunuzda isimler varsa, o kadar iyi). Anonim bir iç sınıf her iki şeye de izin verir:

new *ParentClassName*(*constructorArgs*) {*members*}

Bu, ParentClassName öğesini genişleten adsız bir sınıfın yeni bir örneğini döndüren bir ifadedir . Kendi kurucunuzu sağlayamazsınız; bunun yerine, sadece süper yapıcıyı çağıran dolaylı olarak sağlanır, böylece sağlanan argümanlar süper yapıcıya uymalıdır. (Üst öğe birden fazla kurucu içeriyorsa, "en basit" olanı denir, ayrıntılı olarak öğrenmeye zahmete girmeyen oldukça karmaşık bir kurallar dizisi tarafından belirlendiği gibi "en basit" olarak adlandırılır - NetBeans veya Eclipse'nin size söylediklerine dikkat edin.)

Alternatif olarak, uygulanacak bir arabirim belirtebilirsiniz:

new *InterfaceName*() {*members*}

Böyle bir bildirim, Object'i genişleten ve InterfaceName uygulayan adlandırılmamış bir sınıfın yeni bir örneğini oluşturur . Yine kendi kurucunuzu sağlayamazsınız; bu durumda, Java dolaylı olarak no-arg, do-nothing yapıcısı sağlar (bu durumda hiçbir zaman yapıcı argümanları olmayacaktır).

Anonim bir iç sınıfa yapıcı veremeseniz de, bir başlatıcı bloğu (herhangi bir yöntemin dışına yerleştirilmiş bir {} bloğu) kullanarak istediğiniz herhangi bir kurulumu yapabilirsiniz.

Anonim bir iç sınıfın, tek bir örnekle yerel bir iç sınıf yaratmanın daha az esnek bir yolu olduğuna dikkat edin. Birden fazla arabirim uygulayan veya Nesne dışında bir sınıfı genişletirken veya kendi yapıcısını belirten arabirimler uygulayan yerel bir iç sınıf istiyorsanız, normal bir yerel iç sınıf adı oluşturmuş olursunuz.


39
Harika hikaye, teşekkürler. Yine de bir hatası var. Rhino.this.variableName tarafından bir iç sınıftan bir dış sınıfın alanlarına erişebilirsiniz.
Thirler

2
Anonim iç sınıflar için kendi kurucunuzu sağlayamasanız da, çift ayraç başlatmayı kullanabilirsiniz. c2.com/cgi/wiki?DoubleBraceInitialization
Casebash

30
Büyük bir açıklama, ama statik iç sınıfların değersiz olmasına katılmıyorum. Statik iç sınıfların kullanımına büyük ölçüde bağlı olan yapıcı modelinin büyük bir varyasyonu için rwhansen.blogspot.com/2007/07/… adresine bakın .
Mansur Siddiqui

9
Ayrıca, statik iç sınıfın değersiz olduğuna da katılmıyorum: iç sınıfta bir numaralandırma istiyorsanız, iç sınıfı statik hale getirmeniz gerekir.
Birisi bir yerde

9
Özel statik iç içe sınıflar da oldukça yararlıdır: bunlara sahip olmak istiyorsunuz, ancak onları ortaya çıkarmak istemiyorsunuz. LinkedList <T> içindeki Giriş <T> veya bir Etkinlik içindeki AsyncTasks (Android) vb.
Gibi

150

Yukarıdaki cevaplarda gerçek farkın netleştiğini sanmıyorum.

Koşulları doğru yapan ilk kişi:

  • Yuvalanmış sınıf, kaynak kodu düzeyinde başka bir sınıfta bulunan bir sınıftır.
  • Statik değiştirici ile bildirirseniz statiktir .
  • Statik olmayan bir iç içe sınıf, iç sınıf olarak adlandırılır. (Statik olmayan iç içe sınıfla kalıyorum.)

Martin'in cevabı şu ana kadar. Ancak asıl soru şudur: İç içe bir sınıfı statik olarak bildirmenin amacı nedir?

Sınıflarınızı yalnızca topikal olarak bir araya getirilmişlerse veya yuvalanmış sınıf yalnızca kapalı sınıfta kullanılıyorsa, sınıflarınızı bir arada tutmak istiyorsanız statik iç içe sınıflar kullanırsınız . Statik iç içe bir sınıf ile diğer tüm sınıflar arasında anlamsal bir fark yoktur.

Statik olmayan yuvalanmış sınıflar farklı bir canavardır. Anonim iç sınıflara benzer şekilde, bu tür iç içe sınıflar aslında kapaklardır. Bu, çevreleyen kapsamını ve çevreleyen örneklerini yakalar ve erişilebilir hale getirir. Belki bir örnek bunu açıklığa kavuşturacaktır. Bir Konteynerin saplamasını görün:

public class Container {
    public class Item{
        Object data;
        public Container getContainer(){
            return Container.this;
        }
        public Item(Object data) {
            super();
            this.data = data;
        }

    }

    public static Item create(Object data){
        // does not compile since no instance of Container is available
        return new Item(data);
    }
    public Item createSubItem(Object data){
        // compiles, since 'this' Container is available
        return new Item(data);
    }
}

Bu durumda, bir alt öğeden üst konteynere referans almak istersiniz. Statik olmayan bir iç içe sınıf kullanarak, bu biraz çalışma olmadan çalışır. Sözdizimiyle Kapsayıcı'nın ek örneğine erişebilirsiniz Container.this.

Aşağıdaki hardcore açıklamaları:

Java bayt kodlarına bakarsanız, derleyici (statik olmayan) iç içe bir sınıf için üretir, daha da netleşebilir:

// class version 49.0 (49)
// access flags 33
public class Container$Item {

  // compiled from: Container.java
  // access flags 1
  public INNERCLASS Container$Item Container Item

  // access flags 0
  Object data

  // access flags 4112
  final Container this$0

  // access flags 1
  public getContainer() : Container
   L0
    LINENUMBER 7 L0
    ALOAD 0: this
    GETFIELD Container$Item.this$0 : Container
    ARETURN
   L1
    LOCALVARIABLE this Container$Item L0 L1 0
    MAXSTACK = 1
    MAXLOCALS = 1

  // access flags 1
  public <init>(Container,Object) : void
   L0
    LINENUMBER 12 L0
    ALOAD 0: this
    ALOAD 1
    PUTFIELD Container$Item.this$0 : Container
   L1
    LINENUMBER 10 L1
    ALOAD 0: this
    INVOKESPECIAL Object.<init>() : void
   L2
    LINENUMBER 11 L2
    ALOAD 0: this
    ALOAD 2: data
    PUTFIELD Container$Item.data : Object
    RETURN
   L3
    LOCALVARIABLE this Container$Item L0 L3 0
    LOCALVARIABLE data Object L0 L3 2
    MAXSTACK = 2
    MAXLOCALS = 3
}

Gördüğünüz gibi derleyici gizli bir alan oluşturur Container this$0. Bu, ekteki örneği belirtmek için Container türünde ek bir parametreye sahip olan yapıcıda ayarlanır. Bu parametreyi kaynakta göremezsiniz ancak derleyici iç içe bir sınıf için örtük olarak oluşturur.

Martin örneği

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

böylece (bayt kodlarında) gibi bir şeyin çağrısına derlenir.

new InnerClass(outerObject)

Bütünlüğü uğruna:

Anonim sınıf , kendisiyle ilişkilendirilmiş bir adı olmayan ve daha sonra başvurulmayan statik olmayan bir iç içe sınıfın mükemmel bir örneğidir.


17
"Statik iç içe sınıf ve diğer tüm sınıflar arasında anlamsal bir fark yoktur." Yuvalanmış sınıf dışında, üst öğenin özel alanlarını / yöntemlerini ve üst sınıf da iç içe geçmiş özel alanlarını / yöntemlerini görebilir.
Brad Cupit

Statik olmayan iç sınıf potansiyel olarak büyük bellek sızıntılarına neden olmaz mı? Her dinleyici oluşturduğunuzda, bir sızıntı yaratır mısınız?
G_V

3
@G_V, bellek sızıntıları için kesinlikle bir potansiyel var çünkü iç sınıfın bir örneği dış sınıfa başvuruda bulunuyor. Bunun gerçek bir sorun olup olmadığı, dış ve iç sınıf örneklerinin nerede ve nasıl yapıldığına bağlıdır.
jrudolph

94

Yukarıdaki cevapların hiçbirinin, uygulama tasarımı açısından iç içe bir sınıf ile statik bir iç içe sınıf arasındaki gerçek farkı açıklayacağını düşünüyorum:

genel bakış

Yuvalanmış bir sınıf statik olmayan veya statik olabilir ve her durumda başka bir sınıf içinde tanımlanan bir sınıftır . Yuvalanmış bir sınıf, yalnızca sınıflandırma için bir sınıf olmalıdır , eğer bir yuvalanmış sınıf diğer sınıflar tarafından yararlıysa (yalnızca çevreleyen değil), üst düzey sınıf olarak bildirilmelidir.

fark

Statik Olmayan Yuvalanmış sınıf : örtülü olarak kapsayıcı sınıfın çevreleme örneğiyle ilişkilidir; bu, çevreleme örneğinin yöntemlerini ve erişim değişkenlerini çağırmanın mümkün olduğu anlamına gelir. Statik olmayan bir iç içe sınıfın yaygın kullanımlarından biri, bir Bağdaştırıcı sınıfı tanımlamaktır.

Statik İç İçe Sınıf : çevreleyen sınıf örneğine erişemez ve bu yöntemdeki yöntemleri çağırır, bu nedenle iç içe geçmiş sınıf sınıfın bir örneğine erişim gerektirmediğinde kullanılmalıdır. Statik iç içe sınıfın yaygın bir kullanımı, dış nesnenin bileşenlerini uygulamaktır.

Sonuç

Dolayısıyla, tasarım açısından ikisinin arasındaki temel fark şudur: statik olmayan iç içe sınıf, konteyner sınıfının örneğine erişebilir, statik olamaz .


: sonucunuzdan "statik olamaz", kabın statik örnekleri bile değil mi? Elbette?
VdeX

Statik iç içe sınıfın yaygın kullanımı RecyclerView ve ListView'da ViewHolder tasarım modelidir.
Hamzeh Soboh

1
Çoğu durumda, kısa cevap daha açık ve daha iyidir. Bu böyle bir örnek.
Eric Wang

32

Basit bir ifadeyle, iç içe sınıflara ihtiyacımız var, çünkü Java kapanış sağlamıyor.

Yuvalanmış Sınıflar, başka bir kapalı sınıfın gövdesi içinde tanımlanan sınıflardır. İki tiptir - statik ve statik olmayan.

Bunlar, ek sınıfın üyeleri olarak kabul edilir, bu nedenle dört erişim belirtecinden herhangi birini belirtebilirsiniz - private, package, protected, public. Bu lüksü, sadece ilan edilebilecek publicya da pakete özel olabilecek üst düzey sınıflarla yapmıyoruz .

Statik iç içe sınıflar üst sınıfın diğer üyelerine erişemezken, iç sınıflar, diğer adıyla yığın olmayan sınıflar üst sınıfın diğer üyelerine erişebilir.

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1statik iç sınıfımızdır ve statik olmayan iç sınıfımızdır Inner2. Aralarındaki en önemli fark, Inner2bir Inner1nesneyi bağımsız olarak oluşturabileceğiniz bir Dış olmadan örnek oluşturamazsınız .

Inner sınıfını ne zaman kullanırsınız?

Bir durum düşünün Class Ave Class B, ilgili Class Berişim için ihtiyaçlarını Class Aüyeleri ve Class Bsadece ilişkilidir Class A. İç sınıflar resme giriyor.

İç sınıf örneği oluşturmak için dış sınıfınızın bir örneğini oluşturmanız gerekir.

OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();

veya

OuterClass.Inner2 inner = new OuterClass().new Inner2();

Statik Inner sınıfını ne zaman kullanırsınız?

Çevreleyen sınıf / üst sınıf örneği ile herhangi bir ilişkisi olmadığını bildiğinizde, statik bir iç sınıf tanımlarsınız. İç sınıfınız dış sınıfın yöntemlerini veya alanlarını kullanmıyorsa, bu sadece bir alan kaybıdır, bu yüzden statik hale getirin.

Örneğin, statik iç içe sınıf için bir nesne oluşturmak için şu sözdizimini kullanın:

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

Statik iç içe bir sınıfın avantajı, çalışmak için içeren sınıf / üst sınıftan bir nesneye ihtiyaç duymamasıdır. Bu, uygulamanızın çalışma zamanında oluşturduğu nesne sayısını azaltmanıza yardımcı olabilir.


3
Bunu mu demek istediniz OuterClass.Inner2 inner = outer.new Inner2();?
Erik Kaplun

4
static inneraçısından bir çelişki.
user207421

Ve iç sınıflar 'yığın olmayan sınıflar' olarak da bilinmez. Kod olmayan metinler için kod biçimlendirmesi kullanmayın ve metin olmayanlar için kullanın.
user207421

30

İşte Java iç sınıfı ve statik iç içe sınıf arasındaki temel farklar ve benzerlikler.

Umarım yardımcı olur!

İç sınıf

  • Dış sınıfa hem örnek hem de statik yöntemlere ve alanlara erişebilir
  • İlk olarak bir dış sınıf örneğine ihtiyaç duyulması için, onu içine alan sınıf örneği ile ilişkilidir ( yeni anahtar kelime yerine dikkat edin ):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
  • Can not herhangi tanımlamak statik üyeleri kendisi

  • Can not var Sınıf veya Arabirim beyanı

Statik iç içe sınıf

  • Dış sınıf örneği yöntemlerine veya alanlarına erişilemiyor

  • Bunu örneklemek için So sınıfını kapsayan herhangi bir örneğiyle ilişkili değildir:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

benzerlikler

  • Hem iç sınıfları bile erişebilir özel alanlar ve yöntemler arasında dış sınıfına
  • Ayrıca Dış sınıf erişebilir özel alanlar ve yöntemlerin arasında iç sınıfları
  • Her iki sınıf da özel, korumalı veya genel erişim değiştiricisine sahip olabilir

Neden İç İçe Sınıflar Kullanılmalı?

Oracle belgelerine göre çeşitli nedenler vardır ( tam belgeler ):

  • Yalnızca tek bir yerde kullanılan sınıfları mantıksal olarak gruplamanın bir yoludur: Bir sınıf yalnızca bir sınıf için faydalıysa, o sınıfa katmak ve ikisini bir arada tutmak mantıklıdır. Bu tür "yardımcı sınıfları" yerleştirmek paketlerini daha akıcı hale getirir.

  • Kapsüllemeyi arttırır: B'nin A olarak özel olarak ilan edilecek A üyelerine erişmesi gereken iki üst düzey sınıf olan A ve B'yi düşünün. B sınıfını A sınıfı içinde saklayarak A'nın üyeleri özel olarak ilan edilebilir ve B onlara erişebilir. Ek olarak, B'nin kendisi dış dünyadan gizlenebilir.

  • Daha okunabilir ve bakımı kolay koda neden olabilir: Küçük sınıfları üst düzey sınıfların içine yerleştirmek, kodu kullanıldığı yere daha yakın yerleştirir.


26

Bence, genellikle takip edilen sözleşme şöyledir:

  • üst düzey sınıf içindeki statik sınıf iç içe bir sınıftır
  • Üst düzey bir sınıf içindeki statik olmayan sınıf , daha fazla iki forma sahip bir iç sınıftır :
    • yerel sınıf - bir yöntem veya yapıcı gövdesi gibi bir bloğun içinde bildirilen adlandırılmış sınıflar
    • anonim sınıf - örnekleri ifadelerde ve ifadelerde oluşturulan adsız sınıflar

Bununla birlikte, hatırlanması gereken birkaç nokta daha vardır:

  • Üst düzey sınıflar ve statik iç içe sınıf, statik iç içe sınıf durumunda, Dış [üst] sınıfının özel statik alanlarına / yöntemlerine statik başvuru yapabilmesi dışında, bunun tersi anlamsal olarak aynıdır.

  • İç sınıflar, Dış [ana] sınıfın ek örneğinin örnek değişkenlerine erişime sahiptir. Ancak, tüm iç sınıfların kapalı örnekleri yoktur, örneğin, statik başlatıcı bloğunda kullanılan anonim bir sınıf gibi statik bağlamlardaki iç sınıflar yoktur.

  • Anonim sınıf varsayılan olarak üst sınıfı genişletir veya üst arabirimi uygular ve başka bir sınıfı genişletmek veya daha fazla arabirim uygulamak için başka bir hüküm yoktur. Yani,

    • new YourClass(){}; anlamına geliyor class [Anonymous] extends YourClass {}
    • new YourInterface(){}; anlamına geliyor class [Anonymous] implements YourInterface {}

Açık kalan daha büyük sorunun hangisini ne zaman kullanacağını hissediyorum. Bu çoğunlukla hangi senaryo ile uğraştığınıza bağlıdır ancak @jrudolph tarafından verilen yanıtı okumak karar vermenize yardımcı olabilir.


15

İç içe sınıf: sınıf içinde sınıf

Türleri:

  1. Statik iç içe sınıf
  2. Statik olmayan iç içe sınıf [İç sınıf]

Fark:

Statik olmayan iç içe sınıf [İç sınıf]

Statik olmayan iç içe sınıfta, iç sınıfın nesnesi dış sınıfın nesnesi içinde bulunur. Böylece dış sınıfın veri üyesine iç sınıf erişilebilir. Bu yüzden iç sınıfın nesnesini yaratmak için önce dış sınıfın nesnesini yaratmalıyız.

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

Statik iç içe sınıf

Statik iç içe sınıfta iç sınıftaki nesnenin dış sınıf nesnesine ihtiyacı yoktur, çünkü "statik" sözcüğü nesne oluşturmaya gerek olmadığını gösterir.

class outerclass A {
    static class nestedclass B {
        static int x = 10;
    }
}

X'e erişmek istiyorsanız, aşağıdaki iç yöntemi yazın

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

13

İç sınıf örneği, dış sınıf örneği oluşturulduğunda oluşturulur. Bu nedenle iç sınıfın üyeleri ve yöntemleri, dış sınıfın örneğinin (nesnesinin) üyelerine ve yöntemlerine erişebilir. Dış sınıf örneği kapsam dışına çıktığında, iç sınıf örnekleri de ortadan kalkar.

Statik iç içe sınıfın somut bir örneği yoktur. Sadece ilk kez kullanıldığında yüklenir (tıpkı statik yöntemler gibi). Yöntemleri ve değişkenleri dış sınıf örneklerine erişimi olmayan tamamen bağımsız bir varlıktır.

Statik iç içe sınıflar dış nesneyle eşleşmez, daha hızlıdır ve yığın / yığın belleği almazlar, çünkü bu tür bir sınıf örneği oluşturmak gerekli değildir. Bu nedenle, temel kural, olabildiğince sınırlı bir kapsamla (private> = class> = korumalı> = public) statik iç içe sınıf tanımlamaya çalışmak ve daha sonra iç sınıfa ("statik" tanımlayıcıyı kaldırarak) dönüştürmek ve gevşetmektir. kapsam, eğer gerçekten gerekliyse.


2
İlk cümle yanlış. Orada 'diye bir şey iç sınıfın örneği' ve bunun örneklerini dış sınıf örneği sonra herhangi bir zamanda oluşturulabilir. İkinci cümle birinci cümleden sonra gelmez.
user207421

11

Belirli durumlarda yararlı olabilecek iç içe statik sınıfların kullanımı hakkında bir incelik vardır.

Statik nitelikler, sınıf yapıcısıyla somutlaştırılmadan önce somutlaştırılırken, iç içe statik sınıfların içindeki statik öznitelikler, sınıfın kurucusu çağrılıncaya kadar veya en azından öznitelikler ilk referanslanana kadar sonlandırılmamış gibi görünmez. 'final' olarak işaretlenirler.

Bu örneği düşünün:

public class C0 {

    static C0 instance = null;

    // Uncomment the following line and a null pointer exception will be
    // generated before anything gets printed.
    //public static final String outerItem = instance.makeString(98.6);

    public C0() {
        instance = this;
    }

    public String makeString(int i) {
        return ((new Integer(i)).toString());
    }

    public String makeString(double d) {
        return ((new Double(d)).toString());
    }

    public static final class nested {
        public static final String innerItem = instance.makeString(42);
    }

    static public void main(String[] argv) {
        System.out.println("start");
        // Comment out this line and a null pointer exception will be
        // generated after "start" prints and before the following
        // try/catch block even gets entered.
        new C0();
        try {
            System.out.println("retrieve item: " + nested.innerItem);
        }
        catch (Exception e) {
            System.out.println("failed to retrieve item: " + e.toString());
        }
        System.out.println("finish");
    }
}

Her ne kadar 'iç içe' ve 'iç öğe' her ikisi de 'statik final' olarak bildirilmiş olsa da. nested.innerItem ayarı, sınıf somutlaştırılana kadar (veya en azından iç içe geçmiş statik öğeye ilk başvurulanana kadar) gerçekleşmez, çünkü başvurduğum satırları yorumlayıp önerilerini kaldırarak, yukarıda. Aynı şey 'outerItem' için de geçerli değildir.

En azından Java 6.0'da gördüğüm şey bu.


10

Terimler birbirinin yerine kullanılır. Eğer bu konuda gerçekten bilgiçlik olmak istiyorsanız, o zaman olabilir statik iç sınıf, hiçbir kapsayan örneği vardır birine başvurmak için "iç içe sınıfı" tanımlar. Kodda şöyle bir şey olabilir:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Yine de bu gerçekten kabul gören bir tanım değil.


2
'statik iç' bir çelişkidir.
user207421

5
İç sınıfı statik olmayan bir iç içe sınıf olarak tanımlayan bir kural değil, JLS'dir. docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Lew Bloch

1
Ve terimler vardır değil 'birbirinin yerine kullanılmaktadır.'
user207421

neden yukarıdaki örnek statik ide hata veriyor
DeV

10

Örnek oluşturma durumunda, statik olmayan iç sınıf örneği, içinde tanımlandığı dış sınıf nesnesinin başvurusu ile oluşturulur. Bu, onun kapsayıcı örneği olduğu anlamına gelir. Ancak statik iç sınıf örneği, dış sınıf nesnesinin başvurusuyla değil, Dış sınıfın başvurusuyla oluşturulur. Bu, onun kapsayıcı örneği olmadığı anlamına gelir.

Örneğin:

class A
{
  class B
  {
    // static int x; not allowed here…..    
  }
  static class C
  {
    static int x; // allowed here
  }
}

class Test
{
  public static void main(String str)
  {
    A o=new A();
    A.B obj1 =o.new B();//need of inclosing instance

    A.C obj2 =new A.C();

    // not need of reference of object of outer class….
  }
}

1
'statik iç' bir çelişkidir. Yuvalanmış bir sınıf statik veya içseldir.
user207421

9

Buraya eklenecek çok şey olduğunu düşünmüyorum, cevapların çoğu statik iç içe sınıf ve iç sınıflar arasındaki farkları mükemmel bir şekilde açıklıyor. Ancak, iç sınıflara karşı iç içe sınıfları kullanırken aşağıdaki sorunu göz önünde bulundurun. Birkaç cevapta belirtildiği gibi, iç sınıflar çevreleyen sınıfları olmadan ve örneklenmeden somutlaştırılamazlar, bu da onların GC sınıfından dolayı bellek taşmasına veya yığın taşması istisnasına yol açabilecek çevreleyen sınıf örneğine bir işaretçi TUTDUĞU anlamına gelir. artık kullanılmasalar bile kapalı sınıfları çöp toplayamazlar. Bunu netleştirmek için aşağıdaki kodu kontrol edin:

public class Outer {


    public  class Inner {

    }


    public Inner inner(){
        return new Inner();
    }

    @Override
    protected void finalize() throws Throwable {
    // as you know finalize is called by the garbage collector due to destroying an object instance
        System.out.println("I am destroyed !");
    }
}


public static void main(String arg[]) {

    Outer outer = new Outer();
    Outer.Inner inner = outer.new Inner();

    // out instance is no more used and should be garbage collected !!!
    // However this will not happen as inner instance is still alive i.e used, not null !
    // and outer will be kept in memory until inner is destroyed
    outer = null;

    //
    // inner = null;

    //kick out garbage collector
    System.gc();

}

Eğer // inner = null;program üzerindeki yorumu kaldırırsanız " Ben yokum! " Yazacak, ama bu yorumda kalmayacak.
Bunun nedeni, beyaz iç örneğe hala başvuruda bulunulmasıyla GC'nin toplanamaması ve dış örneğe başvurması (bir işaretçisi olduğundan) de toplanmaz. Projenizde bu nesnelerin yeterli olması ve belleğiniz bitebilir.
Örnekle ilgili değil, sınıfla ilgili olduğu için iç sınıf örneğine bir nokta tutmayan statik iç sınıflarla karşılaştırıldığında. Eğer Inner sınıfını statik ve somutlaştırılmış yaparsanız yukarıdaki program " imha oldum! "Outer.Inner i = new Outer.Inner();




8

Ummm ... bir iç sınıf İç içe bir sınıf mı ... anonim sınıf ve iç sınıf mı demek istiyorsun?

Düzenleme: Aslında iç vs anonim demekti ... bir iç sınıf sadece bir sınıf içinde tanımlanan bir sınıftır:

public class A {
    public class B {
    }
}

Anonim sınıf, anonim olarak tanımlanan bir sınıfın uzantısıdır, bu nedenle aşağıdaki gibi gerçek bir "sınıf tanımlanmaz:

public class A {
}

A anon = new A() { /* you could change behavior of A here */ };

Diğer Düzenlemeler:

Wikipedia bir fark olduğunu iddia ediyor , Java'da , ancak 8 yıldır Java ile çalışıyorum ve bu tür bir ayrım duyduğum ilk şey ... iddiayı destekleyecek referanslar olmadığından bahsetmiyorum ... alt iç sınıf, sınıf içinde tanımlanan (statik ya da değil) bir sınıftır ve iç içe geçen, aynı anlama gelen başka bir terimdir.

Statik ve statik olmayan iç içe sınıf arasında ince bir fark vardır ... temel olarak statik olmayan iç sınıflar, kapalı sınıfın örnek alanlarına ve yöntemlerine örtük erişime sahiptir (böylece statik bir bağlamda inşa edilemezler, bir derleyici olacaktır. hata). Statik iç içe sınıflar, örnek alanlarına ve yöntemlerine örtük erişime sahip değildir ve statik bir bağlamda oluşturulabilir.


3
Java belgelerine göre, bir iç sınıf ile statik bir iç içe sınıf arasında bir fark vardır - statik iç içe sınıfların, kapalı sınıflarına referansları yoktur ve temel olarak kuruluş amacıyla kullanılır. Daha ayrıntılı bir açıklama için Jegschemesch'in cevabını görmelisiniz.
mipadi

1
Bence anlambilimsel fark çoğunlukla tarihseldir. Bir C # -> Java 1.1 derleyicisi yazdığımda, Java dili başvurusu çok açıktı: iç içe sınıf statik, iç sınıf değil (ve bu nedenle bu 0 $). Ne olursa olsun kafa karıştırıcı ve sevindim artık bir sorun değil.
Tomer Gabel

2
JLS, docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3'te "iç sınıfı" tanımlar ve bu nedenle statik olmayan bir iç kısma sahip olmak imkansızdır sınıf ". "İç içe", "aynı anlama gelen başka bir terim" DEĞİLDİR ve "bir iç sınıf, sınıf içinde tanımlanan (statik ya da değil) bir sınıftır" DOĞRU DEĞİLDİR. Bu YANLIŞ bilgidir.
Lew Bloch

6

Java ve / veya İç İçe Sınıflara acemi olan öğrenciyi hedefleme

Yuvalanmış sınıflar şunlardan biri olabilir:
1. Statik Yuvalanmış sınıflar.
2. Statik Olmayan Yuvalanmış sınıflar. ( İç sınıflar olarak da bilinir ) => Lütfen bunu hatırlayın


1.İç sınıflar
Örnek:

class OuterClass  {
/*  some code here...*/
     class InnerClass  {  }
/*  some code here...*/
}


İç sınıflar iç içe sınıfların alt kümeleridir:

  • iç sınıf, belirli bir iç içe sınıf türüdür
  • iç sınıflar iç içe sınıfların alt kümeleridir
  • Bir söyleyebiliriz iç sınıfı da iç içe bir sınıf, ama olabilir DEĞİL iç içe geçmiş bir sınıfı da bir iç sınıf olduğunu söylemek .

İç sınıf uzmanlığı:

  • bir iç sınıf örneği, “özel” olarak işaretlenmiş olsalar bile, dış sınıfın tüm üyelerine erişebilir


2.Statik İç İçe Sınıflar:
Örnek:

class EnclosingClass {
  static class Nested {
    void someMethod() { System.out.println("hello SO"); }
  }
}

Durum 1: Çevreleyen olmayan bir sınıftan statik iç içe sınıfın örneklenmesi

class NonEnclosingClass {

  public static void main(String[] args) {
    /*instantiate the Nested class that is a static
      member of the EnclosingClass class:
    */

    EnclosingClass.Nested n = new EnclosingClass.Nested(); 
    n.someMethod();  //prints out "hello"
  }
}

Durum 2: Çevreleyen bir sınıftan statik iç içe sınıfın örneklenmesi

class EnclosingClass {

  static class Nested {
    void anotherMethod() { System.out.println("hi again"); } 
  }

  public static void main(String[] args) {
    //access enclosed class:

    Nested n = new Nested(); 
    n.anotherMethod();  //prints out "hi again"
  }

}

Statik sınıfların uzmanlığı:

  • Statik iç sınıf yalnızca dış sınıfın statik üyelerine erişebilir ve statik olmayan üyelere erişemez.

Sonuç:
Soru: Java'da bir iç sınıf ile statik iç içe bir sınıf arasındaki temel fark nedir?
Cevap: sadece yukarıda belirtilen her sınıfın özelliklerini gözden geçirin.



6

İç sınıf ve iç içe statik sınıfJava'daki , Java'da üst düzey sınıf olarak bilinen başka bir sınıfın içinde bildirilen sınıflardır. Java terminolojisinde, iç içe bir sınıf statik bildirirseniz, Java'da iç içe statik sınıf olarak adlandırılırken, statik olmayan iç içe sınıf yalnızca İç Sınıf olarak adlandırılır.

Java'da İç Sınıf nedir?

Üst düzey olmayan veya başka bir sınıfın içinde bildirilen herhangi bir sınıf, iç içe sınıf olarak bilinir ve bu iç içe sınıfların dışında, statik olmayan olarak adlandırılan sınıf, Java'da İç sınıf olarak bilinir. Java'da üç tür İç sınıf vardır:

1) Yerel iç sınıf - bir kod bloğu veya yöntemi içinde bildirilir.
2) Anonim iç sınıf - başvurulacak adı olmayan ve oluşturulduğu yerde başlatılan bir sınıftır.
3) Üye iç sınıfı - dış sınıfın statik olmayan üyesi olarak ilan edilir.

public class InnerClassTest {
    public static void main(String args[]) {      
        //creating local inner class inside method i.e. main() 
        class Local {
            public void name() {
                System.out.println("Example of Local class in Java");

            }
        }      
        //creating instance of local inner class
        Local local = new Local();
        local.name(); //calling method from local inner class

        //Creating anonymous inner class in Java for implementing thread
        Thread anonymous = new Thread(){
            @Override
            public void run(){
                System.out.println("Anonymous class example in java");
            }
        };
        anonymous.start();

        //example of creating instance of inner class
        InnerClassTest test = new InnerClassTest();
        InnerClassTest.Inner inner = test.new Inner();
        inner.name(); //calling method of inner class
    }

     //Creating Inner class in Java
    private class Inner{
        public void name(){
            System.out.println("Inner class example in java");
        }
    }
}

Java'da iç içe statik sınıf nedir?

İç içe statik sınıf, sınıf içinde üye olarak bildirilen ve statik hale getirilen başka bir sınıftır. Yuvalanmış statik sınıf aynı zamanda dış sınıfın üyesi olarak bildirilir ve özel, genel veya diğer herhangi bir üye gibi korunabilir. İç içe geçmiş statik sınıfın iç sınıfa göre en önemli avantajlarından biri, iç içe geçmiş statik sınıf örneğinin, Dış sınıfın herhangi bir kapalı örneğine eklenmemesidir. Java'da iç içe statik sınıf örneği oluşturmak için herhangi bir Dış sınıf örneğine de ihtiyacınız yoktur .

1) Özel dahil dış sınıf statik veri üyelerine erişebilir .
2) Statik iç içe sınıf, statik olmayan (örnek) veri üyesine veya yönteme erişemez .

public class NestedStaticExample {
    public static void main(String args[]){  
        StaticNested nested = new StaticNested();
        nested.name();
    }  
    //static nested class in java
    private static class StaticNested{
        public void name(){
            System.out.println("static nested class example in java");
        }
    }
}

Ref: Java ile iç sınıf ve iç içe Statik Sınıf


2
"Statik iç içe sınıf, statik olmayan (örnek) veri üyesine veya yönteme erişemiyor." yanlıştır ve karışıklığa neden olur . Bu örnek bilgilerine erişmek için bir örnek oluşturmaları koşuluyla, özel örnek bilgilerine kesinlikle erişimleri vardır. İç sınıfların yaptığı gibi bir çevreleyen örneğe sahip değiller, ancak çevreleyen sınıflarının yönetimsel özel üyelerine erişimleri var.
TJ Crowder

5

Sanırım buradaki insanlar Poster'e şunu bildirmelidir: Statik Yuva Sınıfı sadece ilk iç sınıf. Örneğin:

 public static class A {} //ERROR

 public class A {
     public class B {
         public static class C {} //ERROR
     }
 }

 public class A {
     public static class B {} //COMPILE !!!

 }

Özetle, statik sınıf hangi sınıfı içerdiğine bağlı değildir. Yani normal sınıfta olamazlar. (çünkü normal sınıfın bir örneğe ihtiyacı vardır).


2
Hepsi saçmalık. Bütün bunlar bir iç sınıfın statik bir sınıf içeremeyeceğidir. 'Hangi sınıfı içerdiğine' ilişkin bölüm, aşağıdaki cümle gibi anlamsızdır.
user207421

5

Bir sınıf içinde statik üye sınıfı bildirdiğimizde, üst düzey iç içe sınıf veya statik iç içe sınıf olarak bilinir. Aşağıdaki gibi gösterilebilir:

class Test{
    private static int x = 1;
        static class A{
        private static int y = 2;
        public static int getZ(){
            return B.z+x;
        }
    }
    static class B{
        private static int z = 3;
        public static int getY(){
            return A.y;
        }
    }
}

class TestDemo{
     public static void main(String[] args){
        Test t = new Test();
        System.out.println(Test.A.getZ());
        System.out.println(Test.B.getY());
    }
}

Bir sınıf içinde statik olmayan üye sınıfını ilan ettiğimizde buna iç sınıf denir. İç sınıf aşağıdaki gibi gösterilebilir:

    class Test{
        private int i = 10;
        class A{
            private int i =20;
            void display(){
            int i = 30;
            System.out.println(i);
            System.out.println(this.i);
            System.out.println(Test.this.i);
        }
    }
}

"Bir sınıf içinde statik üye sınıfı bildirdiğimizde, üst düzey iç içe sınıf olarak bilinir" Bu mantıklı değil. " Üst düzey bir sınıf, iç içe bir sınıf olmayan bir sınıftır." "Üst düzey iç içe sınıf" diye bir şey yoktur.
Radiodef

3

Aşağıdaki örneğidir static nested classve inner class:

OuterClass.java

public class OuterClass {
     private String someVariable = "Non Static";

     private static String anotherStaticVariable = "Static";  

     OuterClass(){

     }

     //Nested classes are static
     static class StaticNestedClass{
        private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable"; 

        //can access private variables declared in the outer class
        public static void getPrivateVariableofOuterClass(){
            System.out.println(anotherStaticVariable);
        }
     }

     //non static
     class InnerClass{

         //can access private variables of outer class
         public String getPrivateNonStaticVariableOfOuterClass(){
             return someVariable;
         }
     }

     public static void accessStaticClass(){
         //can access any variable declared inside the Static Nested Class 
         //even if it private
         String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable; 
         System.out.println(var);
     }

}

OuterClassTest:

public class OuterClassTest {
    public static void main(String[] args) {

        //access the Static Nested Class
        OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();

        //test the private variable declared inside the static nested class
        OuterClass.accessStaticClass();
        /*
         * Inner Class Test
         * */

        //Declaration

        //first instantiate the outer class
        OuterClass outerClass = new OuterClass();

        //then instantiate the inner class
        OuterClass.InnerClass innerClassExample =  outerClass. new InnerClass();

        //test the non static private variable
        System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass()); 

    }

}

3

Yukarıdaki yanıtların hiçbirinin, uygulama tasarımı açısından iç içe bir sınıf ile statik bir iç içe sınıf arasındaki farkı size gerçek bir örnek vermediğini düşünüyorum. Statik iç içe sınıf ile iç sınıf arasındaki temel fark, dış sınıf örneği alanına erişim yeteneğidir.

Aşağıdaki iki örneğe bir göz atalım.

Statik yuva sınıfı: Statik yuvalanmış sınıfların kullanımına iyi bir örnek oluşturucu kalıbıdır ( https://dzone.com/articles/design-patterns-the-builder-pattern ).

BankAccount için statik iç içe bir sınıf kullanıyoruz, çünkü

  1. Statik yuva sınıfı örneği dış sınıftan önce oluşturulabilir.

  2. Oluşturucu deseninde, oluşturucu BankAccount oluşturmak için kullanılan bir yardımcı sınıftır.

  3. BankAccount.Builder yalnızca BankAccount ile ilişkilidir. BankAccount.Builder ile ilgili başka sınıf yoktur. bu yüzden isim kuralını kullanmadan onları organize etmek daha iyidir.
public class BankAccount {

    private long accountNumber;
    private String owner;
    ...

    public static class Builder {

    private long accountNumber;
    private String owner;
    ...

    static public Builder(long accountNumber) {
        this.accountNumber = accountNumber;
    }

    public Builder withOwner(String owner){
        this.owner = owner;
        return this; 
    }

    ...
    public BankAccount build(){
            BankAccount account = new BankAccount(); 
            account.accountNumber = this.accountNumber;
            account.owner = this.owner;
            ...
            return account;
        }
    }
}

İç sınıf: İç sınıfların ortak kullanımı bir olay işleyici tanımlamaktır. https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html

MyClass için iç sınıfı kullanıyoruz, çünkü:

  1. İç sınıf MyAdapter'ın dış sınıf üyesine erişmesi gerekir.

  2. Örnekte, MyAdapter yalnızca MyClass ile ilişkilendirilmiştir. MyAdapter ile ilişkili başka sınıf yok. bu yüzden bir isim kuralı kullanmadan onları organize etmek daha iyidir

public class MyClass extends Applet {
    ...
        someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
            ...// Event listener implementation goes here...
            ...// change some outer class instance property depend on the event
        }
    }
}

2

Bir diyagram

resim açıklamasını buraya girin

Arasındaki temel fark static nestedve non-static nestedsınıflara yani static nested yok statik olmayan dış sınıf üyelerine bir erişim


0

Her şeyden önce Statik sınıf diye bir sınıf yoktur. İç sınıfla (İç İçe Sınıf olarak adlandırılır) Statik değiştirici kullanımı, Dış Sınıf'ın statik bir üyesi olduğunu, yani diğer statik üyelerle olduğu gibi ve herhangi bir sahip olmadan erişebileceğimiz anlamına gelir. Dış sınıf örneği. (Bu, başlangıçta statikin yararıdır.)

Nested sınıfını ve normal Inner sınıfını kullanma arasındaki fark:

OuterClass.InnerClass inner = new OuterClass().new InnerClass();

Önce Outerclass'ı başlatabiliriz, sonra Inner'a erişebiliriz.

Ancak Class Nested ise sözdizimi şöyledir:

OuterClass.InnerClass inner = new OuterClass.InnerClass();

Statik anahtar kelimenin normal uygulaması olarak statik Sözdizimini kullanır.


1
“... bunun Outer Class'ın statik bir üyesi olduğunu söyler, yani ....”: Statik iç içe bir sınıfı Outer Class'ın “üye sınıfı” olarak düşünmek yanlış değildir, ancak statik alanlarla ve yöntemler burada biter. Statik iç içe bir sınıf, Dış Sınıf'a "ait değildir". Önemli olan hemen hemen her şekilde, statik iç içe geçmiş sınıf, ambalaj tanımı, ambalaj kolaylığı için Dış Sınıf'ın içine yerleştirilmiş olan ve ayakta iç içe sınıf ile Dış Sınıf arasında mantıklı bir ilişki olduğu için, ayakta duran üst düzey bir sınıftır. ... bir tane olmamasına rağmen).
scottb

1
'statik iç' bir çelişkidir. Statik sınıflar, ilk yuvalama seviyesinde vardır ve tanım gereği iç sınıflar değildir. Çok karışık.
user207421

0

Java programlama dili, başka bir sınıf içindeki bir sınıfı tanımlamanızı sağlar. Böyle bir sınıfa iç içe sınıf denir ve burada gösterilmiştir:

class OuterClass {
...
class NestedClass {
    ...
    }
}

İç içe sınıflar iki kategoriye ayrılır: statik ve statik olmayan. Statik olarak bildirilen iç içe sınıflara statik iç içe sınıflar denir. Statik olmayan iç içe sınıflara iç sınıf denir. Aklımızda tutmamız gereken bir şey, statik olmayan iç içe sınıfların (iç sınıflar), özel olarak bildirilmiş olsalar bile, kapalı sınıfın diğer üyelerine erişebilmesidir. Statik iç içe sınıflar, yalnızca statikse, kapalı sınıfın diğer üyelerine erişebilir. Dış sınıfın statik olmayan üyelerine erişemez. Sınıf yöntemleri ve değişkenlerinde olduğu gibi, statik iç içe bir sınıf dış sınıfıyla ilişkilidir. Örneğin, statik iç içe sınıf için bir nesne oluşturmak için şu sözdizimini kullanın:

OuterClass.StaticNestedClass nestedObject =
 new OuterClass.StaticNestedClass(); 

Bir iç sınıfı somutlaştırmak için önce dış sınıfı somutlaştırmalısınız. Ardından, bu sözdizimiyle dış nesnenin içindeki iç nesneyi oluşturun:

OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();

Neden iç içe dersler kullanıyoruz

  1. Yalnızca tek bir yerde kullanılan sınıfları mantıksal olarak gruplamanın bir yoludur.
  2. Kapsüllemeyi arttırır.
  3. Daha okunabilir ve bakımı kolay koda yol açabilir.

Kaynak: Java ™ Eğiticileri - İç İçe Sınıflar


-1

Aradaki fark, aynı zamanda statik olan iç içe bir sınıf bildiriminin, kapalı sınıfın dışında başlatılabilmesidir.

İç sınıf olarak da bilinen statik olmayan iç içe bir sınıf bildiriminiz olduğunda , Java bunu ek sınıf dışında başlatmanıza izin vermez. İç sınıftan oluşturulan nesne, dış sınıftan oluşturulan nesneye bağlanır, böylece iç sınıf dış alanlara başvurabilir.

Ancak statikse, bağlantı mevcut değilse, dış alanlara erişilemez (diğer nesneler gibi sıradan bir başvuru dışında) ve bu nedenle iç içe sınıfı kendiniz başlatabilirsiniz.


1
Bu doğru değil. Çevreleyen sınıfın kapsamı dışında bir iç sınıf oluşturmak için özel bir sözdizimi vardır.
user207421

-1

Oldukça basit, statik yerel sınıfları ve statik olmayan iç sınıfları karşılaştırmak
Farklılıklar:
Statik yerel sınıf:
Sadece dış sınıfın statik üyelerine erişebilir.
Statik başlatıcıları
olamaz Bildirildiği fonksiyonun dışından doğrudan erişilemez


-2

Java kodunda ortaya çıkabilecek çeşitli olası doğru ve hata senaryosunu gösterdim.

    class Outter1 {

        String OutStr;

        Outter1(String str) {
            OutStr = str;
        }

        public void NonStaticMethod(String st)  {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            //  below static attribute not permitted
            // static String tempStatic1 = "static";    

            //  below static with final attribute not permitted         
            // static final String  tempStatic1 = "ashish";  

            // synchronized keyword is not permitted below          
            class localInnerNonStatic1 {            

                synchronized    public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /* 
        //  static method with final not permitted
          public static void innerStaticMethod(String str11) { 

                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }                            

        }

        public static  void StaticMethod(String st)     {

            String temp1 = "ashish";
            final String  tempFinal1 = "ashish"; 

            // static attribute not permitted below
            //static String tempStatic1 = "static";     

            //  static with final attribute not permitted below
            // static final String  tempStatic1 = "ashish";                         

            class localInnerNonStatic1 {
                public void innerMethod(String str11) {
                    str11 = temp1 +" sharma";
                    System.out.println("innerMethod ===> "+str11);
                }

                /*
    // static method with final not permitted
    public static void innerStaticMethod(String str11) {  
                    str11 = temp1 +" india";
                    System.out.println("innerMethod ===> "+str11);
                }*/
            }

            // static class not permitted below
            //  static class localInnerStatic1 {   }    

        }

        // synchronized keyword is not permitted
        static  class inner1 {          

            static String  temp1 = "ashish";
            String  tempNonStatic = "ashish";
            // class localInner1 {

            public void innerMethod(String str11) {
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            public static void innerStaticMethod(String str11) {
                //  error in below step
                str11 = temp1 +" india";    
                //str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }
            //}
        }

        //synchronized keyword is not permitted below
        class innerNonStatic1 {             

//This is important we have to keep final with static modifier in non
// static innerclass below
            static final String  temp1 = "ashish";  
            String  tempNonStatic = "ashish";
            // class localInner1 {

            synchronized    public void innerMethod(String str11) {
                tempNonStatic = tempNonStatic +" ...";
                str11 = temp1 +" sharma";
                str11 = str11+ tempNonStatic +" sharma";
                System.out.println("innerMethod ===> "+str11);
            }

            /*
            //  error in below step
            public static void innerStaticMethod(String str11) {   
                            //  error in below step
                            // str11 = tempNonStatic +" india";                     
                            str11 = temp1 +" india";
                            System.out.println("innerMethod ===> "+str11);
                        }*/
                    //}
                }
    }

1
Açıkçası kod kısmı. Fark etmediyseniz: kod örneğinizi okumak çok zor. Büyük masaüstü monitörümde bile yatay bir kaydırma çubuğum var. Yorumlarınızı arkalarında değil, yorum yaptıkları şeyin üstüne veya altına koymayı düşünün .
GhostCat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.