Jawaban:
Dari Tutorial Java :
Kelas bersarang dibagi menjadi dua kategori: statis dan non-statis. Kelas bersarang yang dideklarasikan statis hanya disebut kelas bersarang statis. Kelas bersarang non-statis disebut kelas dalam.
Kelas bersarang statis diakses menggunakan nama kelas terlampir:
OuterClass.StaticNestedClass
Misalnya, untuk membuat objek untuk kelas bersarang statis, gunakan sintaks ini:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Objek yang merupakan instance dari kelas dalam ada di dalam instance dari kelas luar. Pertimbangkan kelas-kelas berikut:
class OuterClass {
...
class InnerClass {
...
}
}
Sebuah instance dari InnerClass hanya dapat ada dalam instance dari OuterClass dan memiliki akses langsung ke metode dan bidang instance yang melampirkan.
Untuk membuat instance kelas dalam, Anda harus terlebih dahulu membuat kelas luar. Lalu, buat objek dalam di dalam objek luar dengan sintaks ini:
OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
lihat: Tutorial Java - Kelas Bersarang
Untuk catatan kelengkapan bahwa ada juga yang namanya kelas dalam tanpa instance turunan :
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
Di sini, new A() { ... }
adalah kelas dalam yang didefinisikan dalam konteks statis dan tidak memiliki instance terlampir.
import OuterClass.StaticNestedClass;
kemudian referensi kelas hanya sebagai OuterClass.
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
?
The tutorial Java mengatakan :
Terminologi: Kelas bersarang dibagi menjadi dua kategori: statis dan non-statis. Kelas bersarang yang dideklarasikan statis hanya disebut kelas bersarang statis. Kelas bersarang non-statis disebut kelas dalam.
Dalam bahasa umum, istilah "bersarang" dan "dalam" digunakan secara bergantian oleh sebagian besar programmer, tetapi saya akan menggunakan istilah yang benar "kelas bersarang" yang mencakup bagian dalam dan statis.
Kelas dapat bersarang ad infinitum , misalnya kelas A dapat berisi kelas B yang berisi kelas C yang berisi kelas D, dll. Namun, lebih dari satu tingkat kelas bersarang jarang terjadi, karena umumnya desain yang buruk.
Ada tiga alasan Anda dapat membuat kelas bersarang:
Ada empat jenis kelas bersarang di Jawa . Secara singkat, mereka adalah:
Biarkan saya menguraikan lebih detail.
Kelas statis adalah jenis yang paling mudah untuk dipahami karena tidak ada hubungannya dengan instance dari kelas yang berisi.
Kelas statis adalah kelas yang dinyatakan sebagai anggota statis kelas lain. Sama seperti anggota statis lainnya, kelas semacam itu benar-benar hanya gantungan yang menggunakan kelas yang mengandung sebagai namespace-nya, misalnya kelas Goat yang dinyatakan sebagai anggota statis kelas Badak dalam paket pizza dikenal dengan nama pizza.Rhino.Goat .
package pizza;
public class Rhino {
...
public static class Goat {
...
}
}
Terus terang, kelas statis adalah fitur yang sangat tidak berharga karena kelas sudah dibagi menjadi ruang nama berdasarkan paket. Satu-satunya alasan nyata untuk membuat kelas statis adalah kelas semacam itu memiliki akses ke anggota statis privat kelasnya, tetapi saya menemukan ini sebagai pembenaran yang cukup lemah untuk fitur kelas statis ada.
Kelas dalam adalah kelas yang dinyatakan sebagai anggota non-statis dari kelas lain:
package pizza;
public class Rhino {
public class Goat {
...
}
private void jerry() {
Goat g = new Goat();
}
}
Seperti halnya dengan kelas statis, kelas dalam dikenal sebagai terkualifikasi dengan nama kelasnya yang mengandung, pizza.Rhino.Goat , tetapi di dalam kelas yang mengandung, itu dapat diketahui dengan nama yang sederhana. Namun, setiap instance dari kelas batin terkait dengan instance tertentu dari kelas yang mengandungnya: di atas, Kambing yang diciptakan dalam jeriken , secara implisit terkait dengan instance Badak ini dalam jeriken . Jika tidak, kami membuat instance Badak terkait menjadi eksplisit saat kami membuat Instansi kambing :
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
(Perhatikan bahwa Anda menyebut tipe dalam hanya sebagai Kambing dalam sintaks baru yang aneh : Java menyimpulkan tipe yang mengandung dari bagian badak . Dan, ya badak baru. Goat () juga akan lebih masuk akal bagi saya.)
Jadi apa manfaatnya bagi kita? Yah, instance kelas dalam memiliki akses ke anggota instance dari instance kelas yang berisi. Anggota instance terlampir ini dirujuk ke dalam kelas batin hanya melalui nama sederhana mereka, bukan melalui ini ( ini dalam kelas batin merujuk ke instance kelas dalam, bukan instance kelas berisi yang terkait):
public class Rhino {
private String barry;
public class Goat {
public void colin() {
System.out.println(barry);
}
}
}
Di kelas dalam, Anda bisa merujuk ini dari kelas yang mengandung sebagai Rhino.this , dan Anda dapat menggunakan ini untuk merujuk kepada anggotanya, misalnya Rhino.this.barry .
Kelas dalam lokal adalah kelas yang dideklarasikan di tubuh metode. Kelas semacam itu hanya diketahui dalam metode mengandungnya, sehingga hanya dapat dipakai dan memiliki anggota yang diakses dalam metode mengandungnya. Keuntungannya adalah bahwa instance kelas dalam lokal terikat dan dapat mengakses variabel lokal akhir dari metode yang mengandung. Ketika instance menggunakan lokal final dari metode yang mengandung, variabel mempertahankan nilai yang dipegangnya pada saat pembuatan instance, bahkan jika variabel telah keluar dari ruang lingkup (ini adalah secara efektif Java mentah, versi penutupan terbatas).
Karena kelas dalam lokal bukan anggota kelas atau paket, itu tidak dinyatakan dengan tingkat akses. (Namun, jelaskan bahwa anggotanya sendiri memiliki tingkat akses seperti di kelas normal.)
Jika kelas dalam lokal dideklarasikan dalam metode instance, instantiasi kelas batin terkait dengan instance yang dipegang oleh metode yang mengandung ini pada saat pembuatan instance, dan sehingga anggota instance kelas yang mengandung dapat diakses seperti dalam sebuah instance kelas batin. Kelas dalam lokal adalah instantiated hanya melalui namanya, misalnya kelas dalam lokal Cat dipakai sebagai Cat baru () , bukan yang baru ini. Kucing () seperti yang Anda harapkan.
Kelas batin anonim adalah cara yang mudah digunakan secara sintaksis untuk menulis kelas batin setempat. Paling umum, kelas dalam lokal dipakai paling banyak hanya sekali setiap kali metode yang mengandung dijalankan. Maka akan lebih baik, jika kita bisa menggabungkan definisi kelas dalam lokal dan instantiasinya tunggal ke dalam satu bentuk sintaksis yang nyaman, dan juga akan menyenangkan jika kita tidak harus memikirkan nama untuk kelas (semakin sedikit tidak membantu beri nama kode Anda, semakin baik). Kelas dalam anonim memungkinkan kedua hal ini:
new *ParentClassName*(*constructorArgs*) {*members*}
Ini adalah ekspresi yang mengembalikan instance baru dari kelas tanpa nama yang memperluas ParentClassName . Anda tidak dapat memasok konstruktor Anda sendiri; sebaliknya, satu disediakan secara implisit yang hanya memanggil konstruktor super, sehingga argumen yang diberikan harus sesuai dengan konstruktor super. (Jika induk berisi beberapa konstruktor, yang "paling sederhana" disebut, "paling sederhana" sebagaimana ditentukan oleh seperangkat aturan yang agak rumit yang tidak layak untuk dipelajari secara terperinci - cukup perhatikan apa yang dikatakan NetBeans atau Eclipse kepada Anda.)
Atau, Anda dapat menentukan antarmuka yang akan diterapkan:
new *InterfaceName*() {*members*}
Deklarasi semacam itu menciptakan instance baru dari kelas tanpa nama yang memperluas Object dan mengimplementasikan InterfaceName . Sekali lagi, Anda tidak dapat memasok konstruktor Anda sendiri; dalam kasus ini, Java secara implisit memasok konstruktor no-arg, do-nothing (sehingga tidak akan pernah ada argumen konstruktor dalam kasus ini).
Meskipun Anda tidak bisa memberikan konstruktor kelas dalam anonim, Anda masih bisa melakukan pengaturan apa pun yang Anda inginkan menggunakan blok penginisialisasi (blok {} ditempatkan di luar metode apa pun).
Jelaskan bahwa kelas batin anonim hanyalah cara yang kurang fleksibel untuk menciptakan kelas batin lokal dengan satu instance. Jika Anda menginginkan kelas dalam lokal yang mengimplementasikan beberapa antarmuka atau yang mengimplementasikan antarmuka sambil memperluas beberapa kelas selain Objek atau yang menentukan konstruktornya sendiri, Anda terjebak membuat kelas dalam lokal bernama biasa.
Saya tidak berpikir perbedaan nyata menjadi jelas dalam jawaban di atas.
Pertama untuk mendapatkan ketentuan yang benar:
Sejauh ini jawaban Martin benar. Namun, pertanyaan sebenarnya adalah: Apa tujuan dari menyatakan kelas bersarang statis atau tidak?
Anda menggunakan kelas bersarang statis jika Anda hanya ingin menjaga kelas Anda bersama-sama jika mereka termasuk bersama secara topikal atau jika kelas bersarang secara eksklusif digunakan dalam kelas terlampir. Tidak ada perbedaan semantik antara kelas bersarang statis dan setiap kelas lainnya.
Kelas bersarang non-statis adalah binatang yang berbeda. Mirip dengan kelas dalam anonim, kelas bersarang tersebut sebenarnya adalah penutupan. Itu berarti mereka menangkap ruang lingkup di sekitarnya dan contoh terlampir mereka dan membuatnya dapat diakses. Mungkin sebuah contoh akan menjelaskan hal itu. Lihat rintisan Kontainer ini:
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);
}
}
Dalam hal ini Anda ingin memiliki referensi dari item anak ke wadah induk. Menggunakan kelas bersarang non-statis, ini berfungsi tanpa beberapa pekerjaan. Anda dapat mengakses instance terlampir dari Container dengan sintaks Container.this
.
Penjelasan lebih hardcore berikut:
Jika Anda melihat bytecodes Java kompiler menghasilkan untuk kelas bersarang (non-statis) itu mungkin menjadi lebih jelas:
// 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
}
Seperti yang Anda lihat, kompiler membuat bidang tersembunyi Container this$0
. Ini diatur dalam konstruktor yang memiliki parameter tambahan tipe Kontainer untuk menentukan contoh terlampir. Anda tidak dapat melihat parameter ini di sumber tetapi kompiler secara implisit menghasilkannya untuk kelas bersarang.
Contoh Martin
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
akan dikompilasi ke panggilan sesuatu seperti (dalam bytecodes)
new InnerClass(outerObject)
Demi kelengkapan:
Kelas anonim adalah contoh sempurna dari kelas bertingkat non-statis yang tidak memiliki nama yang terkait dengannya dan tidak dapat direferensikan nanti.
Saya pikir tidak ada jawaban di atas yang menjelaskan kepada Anda perbedaan nyata antara kelas bersarang dan kelas bertingkat statis dalam hal desain aplikasi:
Kelas bersarang bisa menjadi tidak statis atau statis dan dalam setiap kasus adalah kelas yang didefinisikan dalam kelas lain . Kelas bersarang harus ada hanya untuk melayani adalah kelas melampirkan , jika kelas bersarang berguna oleh kelas lain (tidak hanya melampirkan), harus dinyatakan sebagai kelas tingkat atas.
Kelas bertingkat Nonstatik : secara implisit dikaitkan dengan instance terlampir dari kelas yang mengandung, ini berarti bahwa dimungkinkan untuk memanggil metode dan variabel akses dari instance melampirkan. Salah satu penggunaan umum dari kelas bertingkat nonstatik adalah untuk mendefinisikan kelas Adaptor.
Static Nested Class : tidak dapat mengakses instance kelas tertutup dan memanggil metode di atasnya, jadi harus digunakan ketika kelas bertingkat tidak memerlukan akses ke instance instance dari kelas penutup. Penggunaan umum dari kelas bersarang statis adalah untuk mengimplementasikan komponen objek luar.
Jadi perbedaan utama antara keduanya dari sudut pandang desain adalah: kelas bersarang nonstatis dapat mengakses instance dari kelas kontainer, sedangkan statis tidak bisa .
Secara sederhana kita membutuhkan kelas bersarang terutama karena Java tidak menyediakan penutupan.
Kelas Bertingkat adalah kelas yang didefinisikan di dalam tubuh kelas penutup lain. Mereka terdiri dari dua jenis - statis dan non-statis.
Mereka diperlakukan sebagai anggota kelas terlampir, maka Anda dapat menentukan salah satu dari empat penentu akses - private, package, protected, public
. Kami tidak memiliki kemewahan ini dengan kelas tingkat atas, yang hanya dapat dideklarasikan public
atau paket-pribadi.
Kelas dalam alias Kelas non-stack memiliki akses ke anggota lain dari kelas atas, bahkan jika mereka dinyatakan pribadi sedangkan kelas bersarang statis tidak memiliki akses ke anggota lain dari kelas atas.
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1
adalah kelas batin kita yang statis dan Inner2
kelas batin kita yang tidak statis. Perbedaan utama di antara mereka, Anda tidak dapat membuat Inner2
instance tanpa Outer di mana Anda dapat membuat Inner1
objek secara mandiri.
Kapan Anda akan menggunakan kelas dalam?
Pikirkan situasi di mana Class A
dan Class B
terkait, Class B
perlu mengakses Class A
anggota, dan Class B
hanya terkait dengan Class A
. Kelas-kelas batin muncul dalam gambar.
Untuk membuat instance dari kelas dalam, Anda perlu membuat instance dari kelas luar Anda.
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
atau
OuterClass.Inner2 inner = new OuterClass().new Inner2();
Kapan Anda akan menggunakan kelas dalam statis?
Anda akan mendefinisikan kelas dalam statis ketika Anda tahu bahwa itu tidak memiliki hubungan dengan turunan kelas atas / kelas atas. Jika kelas dalam Anda tidak menggunakan metode atau bidang dari kelas luar, itu hanya buang-buang ruang, jadi buatlah itu statis.
Misalnya, untuk membuat objek untuk kelas bersarang statis, gunakan sintaks ini:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
Keuntungan dari kelas bersarang statis adalah bahwa ia tidak memerlukan objek dari kelas yang mengandung / kelas atas untuk bekerja. Ini dapat membantu Anda mengurangi jumlah objek yang dibuat aplikasi saat runtime.
OuterClass.Inner2 inner = outer.new Inner2();
?
static inner
adalah kontradiksi dalam hal.
Berikut adalah perbedaan dan persamaan utama antara kelas dalam Java dan kelas bersarang statis.
Semoga ini bisa membantu!
Terkait dengan instance dari menyertakan kelas sehingga untuk instantiate itu pertama membutuhkan instance dari kelas luar (perhatikan tempat kata kunci baru ):
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
Tidak dapat menentukan anggota statis itu sendiri
Tidak dapat mengakses luar kelas misalnya metode atau bidang
Tidak terkait dengan instance dari menyertakan kelas Jadi untuk instantiate itu:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Menurut dokumentasi Oracle ada beberapa alasan ( dokumentasi lengkap ):
Ini adalah cara pengelompokan kelas secara logis yang hanya digunakan di satu tempat: Jika kelas hanya berguna untuk satu kelas lain, maka logis untuk menanamkannya di kelas itu dan menjaga keduanya bersama-sama. Menempatkan "kelas pembantu" seperti itu membuat paket mereka lebih efisien.
Ini meningkatkan enkapsulasi: Pertimbangkan dua kelas tingkat atas, A dan B, di mana B membutuhkan akses ke anggota A yang dinyatakan dinyatakan pribadi. Dengan menyembunyikan kelas B dalam kelas A, anggota A dapat dinyatakan pribadi dan B dapat mengaksesnya. Selain itu, B sendiri dapat disembunyikan dari dunia luar.
Ini dapat menyebabkan kode lebih mudah dibaca dan dipelihara: Bersarang kelas kecil dalam kelas tingkat atas menempatkan kode lebih dekat ke tempat kode itu digunakan.
Saya pikir, konvensi yang diikuti umumnya adalah ini:
Namun, beberapa poin lain yang perlu diingat adalah:
Kelas tingkat atas dan kelas bersarang statis secara semantik sama kecuali jika dalam kasus kelas bersarang statis dapat membuat referensi statis ke bidang / metode statis privat dari kelas [induk] luarnya dan sebaliknya.
Kelas dalam memiliki akses ke variabel instance dari instance terlampir dari kelas [induk] Luar. Namun, tidak semua kelas dalam memiliki instance yang terlampir, misalnya kelas dalam dalam konteks statis, seperti kelas anonim yang digunakan dalam blok penginisialisasi statis, tidak.
Kelas anonim secara default memperluas kelas induk atau mengimplementasikan antarmuka induk dan tidak ada klausa lebih lanjut untuk memperluas kelas lain atau mengimplementasikan antarmuka lagi. Begitu,
new YourClass(){};
cara class [Anonymous] extends YourClass {}
new YourInterface(){};
cara class [Anonymous] implements YourInterface {}
Saya merasa bahwa pertanyaan yang lebih besar yang tetap terbuka mana yang digunakan dan kapan? Yah itu sebagian besar tergantung pada skenario apa yang Anda hadapi tetapi membaca jawaban yang diberikan oleh @jrudolph dapat membantu Anda membuat beberapa keputusan.
Nested class: kelas di dalam kelas
Jenis:
Perbedaan:
Kelas bersarang non-statis [Kelas dalam]
Dalam objek kelas bersarang non-statis kelas dalam ada di dalam objek kelas luar. Sehingga data anggota kelas luar dapat diakses oleh kelas dalam. Jadi untuk membuat objek kelas dalam, kita harus membuat objek kelas luar terlebih dahulu.
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
Kelas bersarang statis
Dalam objek kelas bersarang statis dari kelas dalam tidak perlu objek dari kelas luar, karena kata "statis" menunjukkan tidak perlu membuat objek.
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
Jika Anda ingin mengakses x, maka tulis metode di dalam berikut ini
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
Instance dari kelas dalam dibuat ketika instance dari kelas luar dibuat. Oleh karena itu anggota dan metode kelas dalam memiliki akses ke anggota dan metode instance (objek) dari kelas luar. Ketika instance dari kelas luar keluar dari ruang lingkup, juga instance kelas dalam tidak ada lagi.
Kelas bersarang statis tidak memiliki contoh konkret. Itu hanya dimuat ketika digunakan untuk pertama kalinya (seperti metode statis). Ini adalah entitas yang sepenuhnya independen, yang metode dan variabelnya tidak memiliki akses ke instance kelas luar.
Kelas bersarang statis tidak digabungkan dengan objek luar, mereka lebih cepat, dan mereka tidak mengambil memori tumpukan / tumpukan, karena itu tidak perlu untuk membuat instance dari kelas tersebut. Oleh karena itu aturan praktisnya adalah mencoba mendefinisikan kelas bersarang statis, dengan ruang lingkup sebatas mungkin (pribadi> = kelas> = dilindungi> = publik), dan kemudian mengonversinya ke kelas dalam (dengan menghapus pengenal "statis") dan melonggarkan ruang lingkup, jika itu benar-benar diperlukan.
Ada kehalusan tentang penggunaan kelas statis bersarang yang mungkin berguna dalam situasi tertentu.
Sedangkan atribut statis di-instantiated sebelum kelas di-instantiated melalui konstruktornya, atribut-atribut statis di dalam kelas-kelas statis bersarang tampaknya tidak akan di-instantiate sampai setelah konstruktor kelas dipanggil, atau setidaknya tidak sampai setelah atribut direferensikan pertama kali, bahkan jika mereka ditandai sebagai 'final'.
Pertimbangkan contoh ini:
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");
}
}
Meskipun 'nested' dan 'innerItem' keduanya dinyatakan sebagai 'final statis'. pengaturan nested.innerItem tidak terjadi sampai setelah kelas instantiated (atau setidaknya tidak sampai setelah item statis bersarang direferensikan pertama kali), karena Anda dapat melihat sendiri dengan mengomentari dan menghapus komentar pada baris yang saya rujuk, atas. Hal yang sama tidak berlaku untuk 'outerItem'.
Setidaknya ini yang saya lihat di Java 6.0.
Istilah ini digunakan secara bergantian. Jika Anda ingin benar-benar bertele-tele tentang hal itu, maka Anda dapat mendefinisikan "kelas bersarang" untuk merujuk ke kelas dalam statis, yang tidak memiliki instance penutup. Dalam kode, Anda mungkin memiliki sesuatu seperti ini:
public class Outer {
public class Inner {}
public static class Nested {}
}
Itu bukan definisi yang diterima secara luas.
Dalam hal membuat instance, instance kelas dalam non-statis dibuat dengan referensi objek kelas luar di mana ia didefinisikan. Ini berarti ada inclosing instance. Tetapi instance dari kelas dalam statis dibuat dengan referensi dari kelas luar, bukan dengan referensi objek dari kelas luar. Ini berarti tidak menyertakan instance.
Sebagai contoh:
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….
}
}
Saya tidak berpikir ada banyak untuk ditambahkan di sini, sebagian besar jawaban dengan sempurna menjelaskan perbedaan antara kelas bersarang statis dan kelas dalam. Namun, pertimbangkan masalah berikut saat menggunakan kelas bersarang vs kelas dalam. Seperti disebutkan dalam beberapa jawaban kelas batin tidak dapat dipakai tanpa dan contoh melampirkan kelas mereka yang berarti bahwa mereka TAHAN sebuah pointer ke instance dari kelas melampirkan mereka yang dapat menyebabkan meluap memori atau stack overflow pengecualian karena fakta GC tidak akan dapat mengumpulkan sampah kelas melampirkan bahkan jika mereka tidak digunakan lagi. Untuk membuatnya lebih jelas, periksa kode berikut:
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();
}
Jika Anda menghapus komentar pada // inner = null;
Program ini akan mengeluarkan " Aku hancur! ", Tetapi menjaga komentar ini tidak akan.
Alasannya adalah bahwa instance dalam putih masih dirujuk GC tidak dapat mengumpulkannya dan karena itu merujuk (memiliki pointer ke) instance luar itu tidak dikumpulkan juga. Memiliki cukup benda-benda ini di proyek Anda dan dapat kehabisan memori.
Dibandingkan dengan kelas dalam statis yang tidak memiliki titik untuk instance kelas dalam karena tidak terkait instance tetapi terkait kelas. Program di atas dapat mencetak " Saya hancur! " Jika Anda membuat kelas dalam statis dan dipakaiOuter.Inner i = new Outer.Inner();
Kelas bertingkat adalah istilah yang sangat umum: setiap kelas yang bukan level atas adalah kelas bertingkat. Kelas dalam adalah kelas bersarang non-statis. Joseph Darcy menulis penjelasan yang sangat bagus tentang Nested, Inner, Member, dan Kelas Tingkat Atas .
Ummm ... kelas dalam adalah kelas bersarang ... maksud Anda kelas anonim dan kelas dalam?
Sunting: Jika Anda benar-benar bermaksud bagian dalam vs anonim ... kelas dalam hanyalah kelas yang didefinisikan dalam kelas seperti:
public class A {
public class B {
}
}
Sedangkan kelas anonim adalah ekstensi dari kelas yang didefinisikan secara anonim, jadi tidak ada kelas "sebenarnya yang didefinisikan, seperti pada:
public class A {
}
A anon = new A() { /* you could change behavior of A here */ };
Edit Lebih Lanjut:
Wikipedia mengklaim ada perbedaan di Jawa, tapi saya sudah bekerja dengan Java selama 8 tahun, dan ini adalah yang pertama saya mendengar perbedaan ... belum lagi tidak ada referensi di sana untuk mendukung klaim ... bawah baris, kelas dalam adalah kelas yang didefinisikan dalam kelas (statis atau tidak), dan bersarang hanyalah istilah lain yang berarti hal yang sama.
Ada perbedaan halus antara kelas bertingkat statis dan non-statis ... pada dasarnya kelas dalam non-statis memiliki akses implisit ke bidang contoh dan metode kelas penutup (sehingga mereka tidak dapat dibangun dalam konteks statis, itu akan menjadi kompiler kesalahan). Kelas bersarang statis, di sisi lain, tidak memiliki akses implisit ke bidang contoh dan metode, dan BISA dibangun dalam konteks statis.
Pelajar penargetan, yang pemula untuk Java dan / atau Kelas Bertingkat
Kelas bersarang dapat berupa:
1. Kelas bersarang statis.
2. Kelas Bersarang Non Statis. (juga dikenal sebagai kelas dalam ) => Harap ingat ini
1.Inner class
Contoh:
class OuterClass {
/* some code here...*/
class InnerClass { }
/* some code here...*/
}
Kelas dalam adalah himpunan bagian dari kelas bersarang:
Keistimewaan kelas dalam:
2. Kelas Bersarang Statis:
Contoh:
class EnclosingClass {
static class Nested {
void someMethod() { System.out.println("hello SO"); }
}
}
Kasus 1: Membuat instance kelas bersarang statis dari kelas yang tidak tertutup
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"
}
}
Kasus 2: Membuat instance kelas bersarang statis dari kelas tertutup
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"
}
}
Keistimewaan kelas Statis:
Kesimpulan:
Pertanyaan: Apa perbedaan utama antara kelas dalam dan kelas bersarang statis di Jawa?
Jawaban: cukup telusuri setiap kelas yang disebutkan di atas.
Kelas dalam dan kelas statis bersarang di Jawa keduanya adalah kelas yang dideklarasikan di dalam kelas lain, yang dikenal sebagai kelas tingkat atas di Jawa. Dalam terminologi Java, Jika Anda mendeklarasikan static class bersarang, itu akan disebut kelas statis bersarang di Jawa sementara kelas bersarang non statis secara sederhana disebut sebagai Inner Class.
Apa itu Inner Class di Jawa?
Setiap kelas yang bukan tingkat atas atau dideklarasikan di dalam kelas lain dikenal sebagai kelas bersarang dan keluar dari kelas bersarang, kelas yang dinyatakan non statis dikenal sebagai kelas dalam di Jawa. ada tiga jenis kelas dalam di Jawa:
1) Kelas dalam lokal - dideklarasikan di dalam blok kode atau metode.
2) Anonim kelas batin - adalah kelas yang tidak memiliki nama untuk referensi dan diinisialisasi di tempat yang sama di mana ia dibuat.
3) Anggota kelas dalam - dinyatakan sebagai anggota non-statis dari kelas luar.
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");
}
}
}
Apa kelas statis bersarang di Jawa?
Kelas statis bersarang adalah kelas lain yang dideklarasikan di dalam kelas sebagai anggota dan dibuat statis. Kelas statis bersarang juga dinyatakan sebagai anggota kelas luar dan dapat dibuat pribadi, publik atau dilindungi seperti anggota lainnya. Salah satu manfaat utama dari kelas statis bersarang atas kelas dalam adalah bahwa instance dari kelas statis bersarang tidak melekat pada instance apa pun dari kelas luar. Anda juga tidak memerlukan turunan dari kelas luar untuk membuat turunan dari kelas statis bersarang di Jawa .
1) Dapat mengakses anggota data statis kelas luar termasuk pribadi.
2) Kelas bersarang statis tidak dapat mengakses anggota atau metode data non-statis .
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: Kelas dalam dan Kelas Statis bersarang di Jawa dengan Contoh
Saya pikir orang-orang di sini harus memperhatikan Poster bahwa: Kelas Sarang Statis hanya kelas batin pertama. Sebagai contoh:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
Jadi, ringkasnya, kelas statis tidak tergantung kelas mana yang berisi. Jadi, mereka tidak bisa di kelas normal. (karena kelas normal membutuhkan instance).
Ketika kami mendeklarasikan kelas anggota statis di dalam kelas, itu dikenal sebagai kelas bertingkat tingkat atas atau kelas bertumpuk statis. Itu bisa ditunjukkan seperti di bawah ini:
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());
}
}
Ketika kita mendeklarasikan kelas anggota non-statis di dalam kelas itu dikenal sebagai kelas dalam. Kelas batin dapat ditunjukkan sebagai berikut:
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);
}
}
}
Berikut ini adalah contoh dari static nested class
dan 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());
}
}
Saya pikir tidak ada jawaban di atas yang memberikan contoh nyata kepada Anda perbedaan antara kelas bersarang dan kelas bersarang statis dalam hal desain aplikasi. Dan perbedaan utama antara kelas bersarang statis dan kelas dalam adalah kemampuan untuk mengakses bidang instance kelas luar.
Mari kita lihat dua contoh berikut.
Kelas sarang statis: Contoh yang baik menggunakan kelas bersarang statis adalah pola pembangun ( https://dzone.com/articles/design-patterns-the-builder-pattern ).
Untuk BankAccount kami menggunakan kelas bersarang statis, terutama karena
Contoh kelas statis statis dapat dibuat sebelum kelas luar.
Dalam pola builder, builder adalah kelas pembantu yang digunakan untuk membuat BankAccount.
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;
}
}
}
Kelas dalam: Penggunaan kelas dalam yang umum adalah untuk mendefinisikan pengendali event. https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html
Untuk MyClass, kami menggunakan kelas dalam, terutama karena:
Kelas dalam MyAdapter perlu mengakses anggota kelas luar.
Dalam contoh ini, MyAdapter hanya dikaitkan dengan MyClass. Tidak ada kelas lain yang terkait dengan MyAdapter. jadi lebih baik mengaturnya bersama tanpa menggunakan konvensi nama
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
}
}
}
Pertama-tama Tidak ada kelas yang disebut kelas Static. Pengubah statis digunakan dengan kelas dalam (disebut sebagai Nested Class) mengatakan bahwa itu adalah anggota statis dari Kelas Luar yang berarti kita dapat mengaksesnya seperti dengan anggota statis lainnya dan tanpa memiliki turunan dari kelas luar. (Yang awalnya merupakan manfaat statis.)
Perbedaan antara menggunakan kelas Nested dan kelas dalam reguler adalah:
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
Pertama kita bisa instantiate Outerclass lalu kita bisa mengakses Inner.
Tetapi jika Class bersarang maka sintaksnya adalah:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
Yang menggunakan Sintaks statis sebagai implementasi normal dari kata kunci statis.
Bahasa pemrograman Java memungkinkan Anda untuk mendefinisikan kelas dalam kelas lain. Kelas semacam itu disebut kelas bersarang dan diilustrasikan di sini:
class OuterClass {
...
class NestedClass {
...
}
}
Kelas bersarang dibagi menjadi dua kategori: statis dan non-statis. Kelas bersarang yang dideklarasikan statis disebut kelas bersarang statis. Kelas bersarang non-statis disebut kelas dalam. Satu hal yang harus diingat adalah kelas bersarang non-statis (kelas dalam) memiliki akses ke anggota lain dari kelas terlampir, bahkan jika mereka dinyatakan pribadi. Kelas bersarang statis hanya memiliki akses ke anggota lain dari kelas terlampir jika mereka statis. Itu tidak dapat mengakses anggota non-statis dari kelas luar. Seperti halnya metode dan variabel kelas, kelas bersarang statis dikaitkan dengan kelas luarnya. Misalnya, untuk membuat objek untuk kelas bersarang statis, gunakan sintaks ini:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
Untuk membuat instance kelas dalam, Anda harus terlebih dahulu membuat kelas luar. Lalu, buat objek dalam di dalam objek luar dengan sintaks ini:
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
Mengapa kami menggunakan kelas bersarang
Perbedaannya adalah bahwa deklarasi kelas bersarang yang juga statis dapat dipakai di luar kelas melampirkan.
Ketika Anda memiliki deklarasi kelas bersarang yang tidak statis, juga dikenal sebagai kelas dalam , Java tidak akan membiarkan Anda instantiate kecuali melalui kelas terlampir. Objek yang dibuat dari kelas dalam dihubungkan dengan objek yang dibuat dari kelas luar, sehingga kelas dalam dapat merujuk bidang bidang luar.
Tetapi jika itu statis, maka tautannya tidak ada, bidang luar tidak dapat diakses (kecuali melalui referensi biasa seperti objek lain) dan karena itu Anda dapat membuat instance kelas bersarang dengan sendirinya.
Saya telah menggambarkan berbagai kemungkinan skenario benar dan salah yang dapat terjadi dalam kode java.
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