it-swarm-id.com

Java inner class dan kelas bersarang statis

Apa perbedaan utama antara kelas dalam dan kelas bersarang statis di Jawa? Apakah desain/implementasi berperan dalam memilih salah satunya?

1585
Omnipotent

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 instance kelas luar. Lalu, buat objek dalam di dalam objek luar dengan sintaks ini:

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

lihat: Tutorial Java - Kelas Bersarang

Untuk catatan kelengkapan bahwa ada juga yang namanya kelas dalam tanpa instance terlampir :

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

Di sini, new A() { ... } adalah kelas bagian dalam yang didefinisikan dalam konteks statis dan tidak memiliki turunan terlampir.

1564
Martin

Tutorial Java mengatakan :

Terminologi: Kelas bersarang adalah dibagi menjadi dua kategori: statis dan tidak statis. Kelas bersarang yang dinyatakan statis hanya disebut kelas bersarang statis. Non-statis kelas bersarang disebut inner kelas.

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, mis. 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:

  • organisasi: kadang-kadang tampaknya paling masuk akal untuk menyortir kelas ke dalam namespace kelas lain, terutama ketika itu tidak akan digunakan dalam konteks lain
  • akses: kelas bersarang memiliki akses khusus ke variabel/bidang kelas yang berisi (tepatnya variabel/bidang mana yang tergantung pada jenis kelas bersarang, apakah bagian dalam atau statis).
  • kenyamanan: harus membuat file baru untuk setiap jenis baru itu merepotkan, sekali lagi, terutama ketika jenis itu hanya akan digunakan dalam satu konteks

Ada empat jenis kelas bersarang di Jawa. Secara singkat, mereka adalah:

  • static class: dideklarasikan sebagai anggota statis kelas lain
  • kelas dalam: dideklarasikan sebagai anggota instance dari kelas lain
  • local inner class: dideklarasikan di dalam metode instance kelas lain
  • kelas batin anonim: seperti kelas dalam lokal, tetapi ditulis sebagai ekspresi yang mengembalikan objek satu kali

Biarkan saya menguraikan lebih detail.


Kelas Statis

Kelas statis adalah jenis yang paling mudah dipahami karena tidak ada hubungannya dengan instance dari kelas yang berisi.

Kelas statis adalah kelas yang dideklarasikan sebagai anggota statis kelas lain. Sama seperti anggota statis lainnya, kelas seperti itu benar-benar hanya gantungan yang menggunakan kelas yang mengandung sebagai namespace-nya, mis kelas Kambing 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 karena kelas seperti itu memiliki akses ke anggota statis privat kelasnya yang mengandung, tetapi saya menemukan ini sebagai pembenaran yang cukup lemah untuk fitur kelas statis ada.


Kelas Batin

Kelas dalam adalah kelas yang dideklarasikan 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 mengandung nama kelasnya, pizza.Rhino.Goat, tetapi di dalam kelas yang mengandung, itu dapat diketahui dengan nama sederhana. Namun, setiap instance dari kelas dalam diikat ke instance tertentu dari kelas yang berisi: di atas, Kambing dibuat dalam jerry, secara implisit terikat dengan Badak instance ini dalam jerry. Kalau tidak, kita membuat instance Badak eksplisit terkait ketika kita instantiate Kambing:

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

(Perhatikan Anda merujuk tipe dalam hanya sebagai Kambing dalam sintaks _ _ ((baru)} _ aneh: Java menyimpulkan tipe berisi dari bagian badak. Dan, ya new rhino.Goat () akan lebih masuk akal bagi saya juga.)

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 via hanya nama-nama sederhana mereka, bukan melaluiini (ini di kelas dalam 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 dapat merujuk ke ini dari kelas yang mengandung Rhino.this, dan Anda dapat menggunakan ini untuk merujuk kepada anggotanya, mis. Rhino.this.barry.


Kelas Dalam Lokal

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 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 dari kelas batin terkait dengan instance yang dipegang oleh metode yang berisi ini pada saat pembuatan instance, dan dengan demikian anggota instance kelas yang mengandung itu dapat diakses seperti dalam kelas batin contoh. Kelas dalam lokal adalah instantiated hanya via namanya, mis kelas dalam lokal Cat dipakai sebagai Cat baru (), bukan baru this.Cat () 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 itu juga akan baik 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*}

new *InterfaceName*() {*members*}

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 ingin kelas dalam lokal yang mengimplementasikan beberapa antarmuka atau yang mengimplementasikan antarmuka sambil memperluas beberapa kelas selain Objek atau yang menentukan konstruktor sendiri, Anda terjebak membuat kelas dalam lokal bernama biasa.

Be clear that an anonymous inner class is simply a less flexible way of creating a local inner class with one instance. If you want a local inner class which implements multiple interfaces or which implements interfaces while extending some class other than Object or which specifies its own constructor, you're stuck creating a regular named local inner class.

553
Jegschemesch

Saya tidak berpikir perbedaan nyata menjadi jelas dalam jawaban di atas. 

Pertama untuk mendapatkan ketentuan yang benar: 

  • Kelas bersarang adalah kelas yang terdapat di kelas lain di tingkat kode sumber.
  • Ini statis jika Anda mendeklarasikannya dengan static modifier.
  • Kelas bersarang non-statis disebut kelas dalam. (Saya tinggal dengan kelas bersarang non-statis.)

Sejauh ini jawaban Martin benar. Namun, pertanyaan sebenarnya adalah: Apa tujuan dari mendeklarasikan kelas bersarang statis atau tidak?

Anda menggunakan kelas bersarang statis jika Anda hanya ingin menjaga kelas Anda bersama-sama jika mereka termasuk bersama-sama 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 bertingkat 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 instance terlampir. Anda tidak dapat melihat parameter ini di sumber tetapi kompilator 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.

131
jrudolph

Saya pikir tidak ada jawaban di atas yang menjelaskan kepada Anda perbedaan nyata antara kelas bersarang dan kelas bertingkat statis dalam hal desain aplikasi: 

OverView

Kelas bersarang bisa nonstatic atau statis dan dalam setiap kasus adalah kelas yang didefinisikan dalam kelas lain . Kelas bersarang harus ada hanya untuk melayani adalah melampirkan kelas , jika kelas bersarang berguna oleh kelas lain (tidak hanya melampirkan), harus dinyatakan sebagai kelas tingkat atas.

Perbedaan

Kelas Nested Nonstatic : secara implisit dikaitkan dengan instance terlampir dari kelas yang mengandung, ini berarti bahwa dimungkinkan untuk memanggil metode dan variabel akses dari instance terlampir. 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 bersarang tidak memerlukan akses ke instance instance dari kelas penutup. Penggunaan umum dari kelas bersarang statis adalah untuk mengimplementasikan komponen objek luar.

Kesimpulan

Jadi perbedaan utama antara keduanya dari sudut pandang desain adalah: kelas bersarang nonstatic dapat mengakses instance dari kelas kontainer, sedangkan statis tidak dapat.

88
aleroot

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 dalam statis kita dan Inner2 adalah kelas dalam kita yang tidak statis. Perbedaan utama di antara mereka, Anda tidak dapat membuat instance Inner2 tanpa Outer di mana Anda dapat membuat objek Inner1 secara mandiri.

Kapan Anda akan menggunakan kelas dalam?

Pikirkan situasi di mana Class A dan Class B terkait, Class B perlu mengakses anggota Class A, dan Class B hanya terkait dengan Class A. Kelas batin muncul di dalam gambar.

Untuk membuat instance kelas dalam, Anda perlu membuat instance 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 kelas luar, itu hanya membuang-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.

31
Thalaivar

Saya pikir, konvensi yang diikuti umumnya adalah ini:

  • kelas statis dalam kelas tingkat atas adalah kelas bersarang
  • kelas non statis dalam kelas tingkat atas adalah kelas dalam, yang selanjutnya.
    • local class - kelas bernama yang dideklarasikan di dalam blok seperti metode atau konstruktor
    • kelas anonim - kelas tanpa nama yang instansnya dibuat dalam ekspresi dan pernyataan

Namun, beberapa poin lain yang perlu diingat adalah:

  • Kelas tingkat atas dan kelas bersarang statis secara semantik sama kecuali bahwa jika kelas bertingkat 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 turunan 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(){}; berarti class [Anonymous] extends YourClass {}
    • new YourInterface(){}; berarti 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.

26
sactiw

Nested class: kelas di dalam kelas

Jenis:

  1. Kelas bersarang statis
  2. Kelas bersarang non-statis [Kelas dalam]

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 batin 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);
15
tejas

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 statis di dalam class-class 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 dari nested.innerItem tidak terjadi sampai setelah kelas instantiated (atau setidaknya tidak sampai setelah item statis bersarang direferensikan pertama kali), seperti yang Anda lihat sendiri.__ oleh komentar dan menghapus komentar pada baris yang saya maksud, di atas. Hal yang sama tidak berlaku .__ berlaku untuk 'outerItem'.

Setidaknya ini yang saya lihat di Java 6.0.

11
HippoMan

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 untuk mencoba mendefinisikan kelas bersarang statis, dengan ruang lingkup sebatas mungkin (pribadi> = kelas> = dilindungi> = publik), dan kemudian mengubahnya ke kelas dalam (dengan menghapus pengenal "statis") dan mengendurkan ruang lingkup, jika itu benar-benar diperlukan.

11
rmaruszewski

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 yang disebutkan dalam beberapa jawaban, kelas dalam tidak dapat di-instantiate tanpa dan instance dari kelas penutup mereka yang berarti bahwa merekaMENAHANa pointer ke instance dari kelas penutup mereka yang dapat menyebabkan ke memory overflow atau stack overflow exception karena fakta GC tidak akan dapat mengumpulkan sampah kelas-kelas yang 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 di // inner = null; Program ini akan mengeluarkan " Saya 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 dipakai dengan Outer.Inner i = new Outer.Inner(); 

10
Adelin

Dalam hal membuat instance, instance kelas dalam statis non .__ dibuat dengan referensi objek .__ kelas luar di mana ia didefinisikan. Ini Berarti memiliki inclosing instance . Tetapi instance dari static class dalam dibuat dengan referensi dari kelas Outer, bukan dengan Referensi objek dari kelas luar Ini artinya Belum menyertakan contoh.

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….
  }
}
10
Ankit Jain

Istilah ini digunakan secara bergantian. Jika Anda ingin benar-benar bertele-tele tentang hal itu, maka Anda bisa mendefinisikan "kelas bersarang" untuk merujuk ke kelas dalam statis, yang tidak memiliki instance terlampir. Dalam kode, Anda mungkin memiliki sesuatu seperti ini:

public class Outer {
    public class Inner {}

    public static class Nested {}
}

Tapi itu bukan definisi yang diterima secara luas.

8
Daniel Spiewak

Kelas bersarang adalah istilah yang sangat umum: setiap kelas yang bukan level teratas adalah kelas bersarang ... Kelas dalam adalah kelas bersarang non-statis . Joseph Darcy menulis penjelasan yang sangat bagus tentang Nested, Inner , Anggota, dan Kelas Tingkat Atas .

8
Wouter Coekaerts

Penargetan pelajar, yang pemula untuk Java dan/atau Kelas Bersarang 

Kelas bersarang dapat berupa:
1. Kelas Bersarang Statis.
2. Kelas Bersarang Non Statis. (juga dikenal sebagai Kelas dalam ) => Harap ingat ini


Kelas 1.Inner
Contoh:

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


Kelas dalam adalah himpunan bagian dari kelas bersarang:

  • kelas batin adalah jenis kelas khusus bersarang
  • kelas batin adalah himpunan bagian dari kelas bersarang
  • Anda dapat mengatakan bahwa kelas batin juga merupakan kelas bertingkat, tetapi Anda dapatTIDAKmengatakan bahwa kelas bertingkat juga merupakan kelas dalam

Spesialisasi kelas dalam:

  • turunan dari kelas dalam memiliki akses ke semua anggota kelas luar, bahkan mereka yang ditandai "pribadi"


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"
  }

}

Keahlian khusus dari kelas Statis:

  • Kelas dalam statis hanya akan memiliki akses ke anggota statis dari kelas luar, dan tidak memiliki akses ke anggota non-statis.

Kesimpulan:
Pertanyaan: Apa perbedaan utama antara kelas dalam dan kelas bersarang statis di Jawa?
Jawab: cukup periksa spesifikasi setiap kelas yang disebutkan di atas.

7
VdeX

Ummm ... kelas dalam IS 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 ... intinya, 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.

7
Mike Stone

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 Kelas Batin 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 tidak 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) Kelas dalam anonim - 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 tidak 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 batin adalah bahwa instance dari kelas statis bersarang tidak melekat pada instance apa pun dari kelas luar. Anda juga tidak memerlukan turunan kelas Outer untuk membuat turunan kelas statis bersarang di Jawa.

1) Dapat mengakses anggota data statis dari kelas luar termasuk pribadi.
2) Kelas bersarang statis tidak dapat mengakses non-statis (contoh) anggota data atau metode.

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

6
roottraveller

Ketika kita 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);
        }
    }
}
5
Pankti

Saya pikir orang-orang di sini harus memperhatikan Poster bahwa: Kelas Sarang Statis hanya kelas batin pertama . Misalnya:

 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).

5
hqt

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()); 

    }

}
3
Pritam Banerjee

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

  1. Contoh kelas statis statis dapat dibuat sebelum kelas luar.

  2. Dalam pola pembangun, pembangun adalah kelas pembantu yang digunakan untuk membuat BankAccount.

  3. BankAccount.Builder hanya terkait dengan BankAccount. Tidak ada kelas lain yang terkait dengan BankAccount.Builder. jadi lebih baik mengaturnya bersama tanpa menggunakan konvensi nama.
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:

  1. Kelas dalam MyAdapter perlu mengakses anggota kelas luar.

  2. Dalam contoh tersebut, 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
        }
    }
}
1
Leogao

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 dinyatakan statis disebut kelas bersarang statis. Kelas bertingkat non-statis disebut kelas dalam . Satu hal yang harus kita ingat adalah kelas bertingkat non-statis (kelas dalam) memiliki akses ke anggota lain dari kelas penutup, 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 yang tidak statis dari kelas luar . Seperti dengan 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 instance 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

  1. Ini adalah cara pengelompokan kelas secara logis yang hanya digunakan di satu tempat.
  2. Ini meningkatkan enkapsulasi.
  3. Ini dapat menyebabkan kode lebih mudah dibaca dan dipelihara.

Sumber: Tutorial Java ™ - Kelas Bertingkat

0
Mithun Debnath

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 Kelas Luar yang berarti kita dapat mengaksesnya seperti dengan anggota statis lain dan tanpa 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.

0
Sohi