Java inner class dan kelas bersarang statis


1766

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


65
Jawaban Joshua Bloch adalah dalam Java baca yang Efektifitem 22 : Favor static member classes over non static
Raymond Chenon

4
Sebagai catatan, item 24 di edisi ke-3 dari buku yang sama.
ZeroCool

Jawaban:


1697

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.


130
Diingat bahwa Anda juga dapat mengimpor kelas bersarang statis langsung, yaitu Anda bisa melakukan (di bagian atas file): import OuterClass.StaticNestedClass; kemudian referensi kelas hanya sebagai OuterClass.
Camilo Díaz Repka

4
@ Martin apakah ada nama teknis khusus untuk idiom ini untuk menciptakan kelas dalam OuterClass.InnerClass innerObject = outerObject.new InnerClass();?
Geek

7
Jadi Apa gunanya kelas bersarang statis privat? Saya pikir kita tidak bisa instantiate dari luar seperti OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass ();
RoboAlex

1
@Ilya Kogan: Maksud saya, saya tahu kita dapat mengakses bidang kelas induk statis atau non-statis (jika kelas anak adalah kelas non-statis) saya telah menggunakan fitur mereka beberapa kali, tetapi saya bertanya-tanya bahwa model memori seperti apa mereka mengikuti? Apakah konsep OOP mencakupnya sebagai konsep terpisah? jika tidak di tempat mereka benar-benar cocok dalam OOP. Sepertinya kelas teman bagi saya :)
Mubashar

4
@martin, saya tahu saya datang ke utas ini sangat terlambat tetapi: Ini adalah variabel Anda, a, itu adalah bidang statis kelas, A. Itu tidak berarti kelas anonim yang dibuat oleh 'new A () {int t () {return 2; }} 'statis lebih daripada jika saya hanya menetapkan objek lain ke bidang statis, a, seperti pada: class B {static void main (string s) {Aa = new A ()}} (A & B di sama package) Ini tidak menjadikan kelas A statis. Frasa "konteks statis," dalam referensi yang dikutip di utas yang Anda tautkan, sangat kabur. Bahkan, ini dicatat dalam banyak komentar di utas itu.
GrantRobertson

599

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:

  • 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:

  • kelas statis : dideklarasikan sebagai anggota statis dari kelas lain
  • kelas batin : dideklarasikan sebagai anggota instance dari kelas lain
  • kelas dalam lokal : dideklarasikan di dalam metode instance dari kelas lain
  • kelas dalam 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 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 Batin

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

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

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.


39
Kisah yang bagus, terima kasih. Tapi ada satu kesalahan. Anda bisa mengakses bidang kelas luar dari kelas dalam instance oleh Rhino.this.variableName.
Thirler

2
Meskipun Anda tidak dapat menyediakan konstruktor sendiri untuk kelas dalam anonim, Anda dapat menggunakan inisialisasi penjepit ganda. c2.com/cgi/wiki?DoubleBraceInisialisasi
Casebash

30
Penjelasan yang bagus, tetapi saya tidak setuju dengan kelas batin statis yang tidak berharga. Lihat rwhansen.blogspot.com/2007/07/... untuk variasi besar pola pembangun yang sangat bergantung pada penggunaan kelas dalam statis.
Mansoor Siddiqui

9
Saya juga tidak setuju bahwa kelas batin statis tidak berharga: jika Anda ingin enum di kelas batin Anda harus membuat kelas dalam statis.
Seseorang di suatu tempat

9
Kelas bersarang statis privat juga cukup berguna: Anda ingin memilikinya, tetapi Anda tidak ingin mengeksposnya. Seperti Entri <T> dalam LinkedList <T>, atau AsyncTasks di dalam Activity (Android), dll ...
Lorenzo Dematté

150

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

Pertama untuk mendapatkan ketentuan yang benar:

  • Kelas bersarang adalah kelas yang terkandung di kelas lain di tingkat kode sumber.
  • Itu statis jika Anda mendeklarasikannya dengan pengubah statis .
  • 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 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.


17
"Tidak ada perbedaan semantik antara kelas bersarang statis dan setiap kelas lainnya." Kecuali kelas bersarang dapat melihat bidang / metode pribadi orang tua dan kelas induk dapat melihat bidang / metode pribadi bersarang.
Brad Cupit

Bukankah kelas dalam non-statis berpotensi menyebabkan kebocoran memori besar? Seperti, setiap kali Anda membuat pendengar, Anda membuat kebocoran?
G_V

3
@ G_V pasti ada potensi kebocoran memori karena turunan dari kelas dalam menyimpan referensi ke kelas luar. Apakah ini merupakan masalah aktual tergantung pada di mana dan bagaimana referensi ke instance kelas luar dan dalam diadakan.
jrudolph

94

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

Gambaran

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.

Perbedaan

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.

Kesimpulan

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


: dari kesimpulan Anda "selagi statis tidak bisa", bahkan contoh statis wadah tidak? Tentu?
VdeX

Penggunaan umum dari kelas bersarang statis adalah pola desain ViewHolder di RecyclerView dan ListView.
Hamzeh Soboh

1
Dalam banyak kasus, jawaban singkatnya lebih jelas, dan lebih baik. Ini adalah contohnya.
Eric Wang

32

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 publicatau 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 {
    }
}

Inner1adalah kelas batin kita yang statis dan Inner2kelas batin kita yang tidak statis. Perbedaan utama di antara mereka, Anda tidak dapat membuat Inner2instance tanpa Outer di mana Anda dapat membuat Inner1objek secara mandiri.

Kapan Anda akan menggunakan kelas dalam?

Pikirkan situasi di mana Class Adan Class Bterkait, Class Bperlu mengakses Class Aanggota, dan Class Bhanya 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.


3
yang Anda maksud OuterClass.Inner2 inner = outer.new Inner2();?
Erik Kaplun

4
static inneradalah kontradiksi dalam hal.
Marquis of Lorne

Dan kelas dalam juga tidak dikenal sebagai 'kelas non-stack'. Jangan gunakan pemformatan kode untuk teks yang bukan kode, dan gunakan untuk teks itu.
Marquis of Lorne

30

Berikut adalah perbedaan dan persamaan utama antara kelas dalam Java dan kelas bersarang statis.

Semoga ini bisa membantu!

Kelas batin

  • Dapat mengakses kelas luar baik instance maupun metode dan bidang statis
  • 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 memiliki deklarasi Kelas atau Antarmuka

Kelas bersarang statis

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

Kesamaan

  • Kedua kelas batin dapat mengakses bahkan bidang swasta dan metode dari kelas luar
  • Juga kelas Outer memiliki akses ke bidang swasta dan metode dari kelas batin
  • Kedua kelas dapat memiliki pengubah akses pribadi, terlindungi atau publik

Mengapa Menggunakan Kelas Bertingkat?

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.


26

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 memiliki dua bentuk lagi:
    • kelas yang dinamai kelas 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 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.


15

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

13

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.


2
Kalimat pertama salah. Tidak ada hal seperti ' yang instance dari kelas batin', dan kasus itu dapat dibuat setiap saat setelah kelas luar telah dipakai. Kalimat kedua tidak mengikuti dari kalimat pertama.
Marquis of Lorne

11

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.


10

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.


2
'statis batin' adalah kontradiksi dalam hal.
Marquis of Lorne

5
Bukan konvensi yang mendefinisikan kelas dalam sebagai kelas bersarang non-statis, tetapi JLS. docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Lew Bloch

1
Dan istilahnya tidak 'digunakan secara bergantian'.
Marquis of Lorne

mengapa statis dalam contoh di atas memberikan kesalahan dalam ide
DeV

10

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….
  }
}

1
'statis batin' adalah kontradiksi dalam hal. Kelas bersarang adalah statis atau batin.
Marquis of Lorne

9

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




8

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.


3
Menurut dokumentasi Java, ada perbedaan antara kelas dalam dan kelas bersarang statis - kelas bersarang statis tidak memiliki referensi ke kelas penutupnya dan digunakan terutama untuk tujuan organisasi. Anda harus melihat balasan Jegschemesch untuk deskripsi yang lebih mendalam.
mipadi

1
Saya pikir perbedaan semantik sebagian besar historis. Ketika saya menulis C # -> Java 1.1 compiler, referensi bahasa Java sangat eksplisit: kelas bersarang adalah statis, kelas dalam tidak (dan dengan demikian memiliki $ 0). Bagaimanapun itu membingungkan dan saya senang itu tidak lagi menjadi masalah.
Tomer Gabel

2
JLS mendefinisikan "kelas dalam" di docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3 dan itulah sebabnya mengapa tidak mungkin untuk memiliki "inner" non-statis. kelas "di Jawa. "Nested" BUKAN "hanya istilah lain yang berarti hal yang sama", dan BUKAN BENAR bahwa "kelas dalam adalah kelas yang didefinisikan dalam kelas (statis atau tidak)". Itu adalah informasi yang TIDAK BENAR.
Lew Bloch

6

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:

  • kelas batin adalah jenis kelas khusus bersarang
  • kelas batin adalah himpunan bagian dari kelas bersarang
  • Anda dapat mengatakan bahwa kelas dalam juga kelas bersarang, tetapi Anda TIDAK bisa mengatakan bahwa kelas bersarang juga merupakan kelas dalam .

Keistimewaan kelas dalam:

  • instance dari kelas batin 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"
  }

}

Keistimewaan 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?
Jawaban: cukup telusuri setiap kelas yang disebutkan di atas.



6

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


2
"Kelas bersarang statis tidak dapat mengakses anggota atau metode data non-statis." salah, dan menyebabkan kebingungan . Mereka benar-benar memiliki akses ke informasi instance pribadi - asalkan mereka membuat instance untuk mengakses informasi instance tersebut pada. Mereka tidak memiliki instance terlampir seperti halnya kelas dalam, tetapi mereka memiliki akses ke anggota pribadi instance kelas terlampir mereka.
TJ Crowder

5

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


2
Ini semua tidak masuk akal. Semua ini menunjukkan bahwa kelas dalam tidak dapat berisi kelas statis. Bagian tentang 'tidak bergantung pada kelas yang dikandungnya' tidak ada artinya, seperti kalimat berikut.
Marquis dari Lorne

5

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

"Ketika kita mendeklarasikan kelas anggota statis di dalam sebuah kelas, itu dikenal sebagai kelas bersarang tingkat atas" Itu tidak masuk akal. " Kelas tingkat atas adalah kelas yang bukan kelas bersarang." Tidak ada yang namanya "kelas bersarang tingkat atas".
Radiodef

3

Berikut ini adalah contoh dari static nested classdan 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

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 builder, builder 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 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
        }
    }
}

2

Diagram

masukkan deskripsi gambar di sini

Perbedaan utama antara static nesteddan non-static nestedkelas adalah bahwa static nested tidak memiliki akses ke anggota kelas luar non-statis


0

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.


1
"... mengatakan bahwa itu adalah anggota statis Kelas Luar yang berarti ....": Tidak salah untuk menganggap kelas bersarang statis sebagai "kelas anggota" Kelas Luar, tetapi kesamaan dengan bidang statis dan metode berakhir di sana. Kelas bersarang statis bukan "milik" Kelas Luar. Dalam hampir setiap hal yang penting, kelas bersarang statis adalah kelas tingkat berdiri bebas atas yang definisi kelasnya bersarang di dalam Kelas Luar untuk kenyamanan pengemasan (dan, mudah-mudahan, karena ada hubungan logis antara kelas bersarang dan Kelas Luar ... meskipun tidak perlu ada satu).
scottb

1
'statis batin' adalah kontradiksi dalam hal. Kelas statis memang ada, pada tingkat bersarang pertama, dan mereka bukan kelas dalam, menurut definisi. Sangat bingung.
Marquis of Lorne

0

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

  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


-1

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.


1
Ini tidak benar. Ada sintaks khusus untuk membuat kelas dalam di luar ruang lingkup kelas penutup.
Marquis of Lorne

-1

Cukup sederhana, membandingkan kelas lokal statis dan kelas dalam non-statis
Perbedaan:
Kelas lokal statis: Hanya
dapat mengakses anggota statis dari kelas luar.
Tidak dapat memiliki penginisialisasi statis.
Tidak dapat diakses langsung dari luar fungsi yang dideklarasikan


-2

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);
                        }*/
                    //}
                }
    }

1
Jelas bagian kode. Dan jika Anda tidak memperhatikan: contoh kode Anda sangat sulit dibaca. Bahkan pada monitor desktop saya yang besar saya mendapat bilah gulir horizontal. Pertimbangkan untuk meletakkan komentar Anda di atas atau di bawah hal yang mereka komentari - bukannya di belakang .
GhostCat
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.