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?
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?
Yanıtlar:
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.
import OuterClass.StaticNestedClass;
o zaman sınıfına atıfta sadece OuterClass olarak.
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
mı?
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:
Orada Java iç içe sınıfın dört çeşit . Kısacası, bunlar:
Daha ayrıntılı olarak açıklayayım.
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ı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 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 ().
İ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.
Yukarıdaki cevaplarda gerçek farkın netleştiğini sanmıyorum.
Koşulları doğru yapan ilk kişi:
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.
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:
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.
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.
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 .
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 public
ya 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 {
}
}
Inner1
statik iç sınıfımızdır ve statik olmayan iç sınıfımızdır Inner2
. Aralarındaki en önemli fark, Inner2
bir Inner1
nesneyi 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 A
ve Class B
, ilgili Class B
erişim için ihtiyaçlarını Class A
üyeleri ve Class B
sadece 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.
OuterClass.Inner2 inner = outer.new Inner2();
?
static inner
açısından bir çelişki.
İş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!
İ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
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();
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.
Bence, genellikle takip edilen sözleşme şöyledir:
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.
İç içe sınıf: sınıf içinde sınıf
Türleri:
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);
İç 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.
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.
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.
Ö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….
}
}
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();
İç içe sınıf çok genel bir terimdir: üst düzey olmayan her sınıf iç içe bir sınıftır. İç sınıf statik olmayan bir iç içe sınıftır. Joseph Darcy , Nested, Inner, Member ve Üst Düzey Sınıflar hakkında çok güzel bir açıklama yazdı .
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.
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:
İç sınıf uzmanlığı:
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ığı:
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.
İç 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");
}
}
}
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).
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);
}
}
}
Aşağıdaki örneğidir static nested class
ve 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());
}
}
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ü
Statik yuva sınıfı örneği dış sınıftan önce oluşturulabilir.
Oluşturucu deseninde, oluşturucu BankAccount oluşturmak için kullanılan bir yardımcı sınıftır.
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ü:
İç sınıf MyAdapter'ın dış sınıf üyesine erişmesi gerekir.
Ö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
}
}
}
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.
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
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.
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);
}*/
//}
}
}
item 22 : Favor static member classes over non static