Kelas Bersarang di Jawa

1. Pengenalan

Tutorial ini adalah pengenalan cepat dan tepat untuk kelas bersarang dalam bahasa Java.

Secara sederhana, Java membolehkan kita menentukan kelas di dalam kelas lain. Kelas bersarang membolehkan kami mengelompokkan kelas secara logik yang hanya digunakan di satu tempat, menulis kod yang lebih mudah dibaca dan dikekalkan dan meningkatkan enkapsulasi.

Sebelum kita memulakan, mari kita lihat beberapa jenis kelas bersarang yang tersedia dalam bahasa:

  • Kelas bersarang statik
  • Kelas bersarang bukan statik
  • Kelas tempatan
  • Kelas tanpa nama

Pada bahagian seterusnya, kita akan membincangkan masing-masing secara terperinci.

2. Kelas Bersarang Statik

Berikut adalah beberapa perkara yang perlu diingat mengenai kelas bersarang statik:

  • Seperti ahli statik, ini termasuk dalam kelas yang merangkumi mereka, dan bukan pada kelas yang lain
  • Mereka boleh mempunyai semua jenis pengubah akses dalam deklarasi mereka
  • Mereka hanya mempunyai akses kepada ahli statik di kelas lampiran
  • Mereka boleh menentukan ahli statik dan bukan statik

Mari lihat bagaimana kita boleh menyatakan kelas bersarang statik:

public class Enclosing { private static int x = 1; public static class StaticNested { private void run() { // method implementation } } @Test public void test() { Enclosing.StaticNested nested = new Enclosing.StaticNested(); nested.run(); } }

3. Kelas Bersarang Bukan Statik

Seterusnya, berikut adalah beberapa perkara cepat untuk diingat mengenai kelas bersarang bukan statik:

  • Mereka juga dipanggil kelas dalaman
  • Mereka boleh mempunyai semua jenis pengubah akses dalam deklarasi mereka
  • Sama seperti pemboleh ubah dan kaedah contoh, kelas dalam dikaitkan dengan contoh kelas yang merangkumi
  • Mereka mempunyai akses kepada semua anggota kelas penutur, tidak kira sama ada mereka statik atau tidak statik
  • Mereka hanya boleh menentukan ahli yang tidak statik

Inilah cara kita dapat menyatakan kelas dalaman:

public class Outer { public class Inner { // ... } }

Sekiranya kita mengisytiharkan kelas bersarang dengan pengubah statik , maka ia adalah ahli statik. Jika tidak, ia adalah kelas dalaman. Walaupun secara sintaksis perbezaannya hanya satu kata kunci (iaitu, statik ), secara semantik terdapat perbezaan besar antara jenis kelas bersarang ini. Contoh kelas dalaman terikat dengan kelas yang merangkumi dan oleh itu mereka mempunyai akses kepada ahli mereka. Kita harus menyedari masalah ini semasa memilih sama ada menjadikan kelas bersarang menjadi kelas dalaman.

Untuk mewujudkan kelas dalaman, pertama-tama kita mesti menunjukkan kelas yang merangkumi.

Mari lihat bagaimana kita dapat melakukannya:

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

Pada bahagian seterusnya, kita akan menunjukkan beberapa jenis kelas dalaman yang khas.

3.1. Kelas Tempatan

Kelas tempatan adalah jenis kelas dalaman khas - di mana kelas ditentukan dalam kaedah atau blok ruang lingkup.

Mari kita lihat beberapa perkara yang perlu diingat mengenai jenis kelas ini:

  • Mereka tidak boleh mempunyai pengubah akses dalam deklarasi mereka
  • Mereka mempunyai akses kepada ahli statik dan bukan statik dalam konteks lampiran
  • Mereka hanya boleh menentukan ahli contoh

Inilah contoh ringkas:

public class NewEnclosing { void run() { class Local { void run() { // method implementation } } Local local = new Local(); local.run(); } @Test public void test() { NewEnclosing newEnclosing = new NewEnclosing(); newEnclosing.run(); } }

3.2. Kelas Tanpa Nama

Kelas tanpa nama dapat digunakan untuk menentukan pelaksanaan antara muka atau kelas abstrak tanpa harus membuat pelaksanaan yang dapat digunakan kembali.

Mari senaraikan beberapa perkara yang perlu diingat mengenai kelas tanpa nama:

  • Mereka tidak boleh mempunyai pengubah akses dalam deklarasi mereka
  • Mereka mempunyai akses kepada ahli statik dan bukan statik dalam konteks lampiran
  • Mereka hanya boleh menentukan ahli contoh
  • Mereka adalah satu-satunya jenis kelas bersarang yang tidak dapat menentukan konstruktor atau memperluas / melaksanakan kelas atau antara muka lain

Untuk menentukan kelas tanpa nama, pertama-tama tentukan kelas abstrak sederhana:

abstract class SimpleAbstractClass { abstract void run(); }

Now let's see how we can define an anonymous class:

public class AnonymousInnerUnitTest { @Test public void whenRunAnonymousClass_thenCorrect() { SimpleAbstractClass simpleAbstractClass = new SimpleAbstractClass() { void run() { // method implementation } }; simpleAbstractClass.run(); } }

For more details, we may find useful our tutorial on Anonymous Classes in Java.

4. Shadowing

The declaration of the members of an inner class shadow those of the enclosing class if they have the same name.

In this case, the this keyword refers to the instances of the nested class and the members of the outer class can be referred to using the name of the outer class.

Let's see a quick example:

public class NewOuter { int a = 1; static int b = 2; public class InnerClass { int a = 3; static final int b = 4; public void run() { System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("NewOuterTest.this.a = " + NewOuter.this.a); System.out.println("NewOuterTest.b = " + NewOuter.b); System.out.println("NewOuterTest.this.b = " + NewOuter.this.b); } } @Test public void test() { NewOuter outer = new NewOuter(); NewOuter.InnerClass inner = outer.new InnerClass(); inner.run(); } }

5. Serialization

To avoid a java.io.NotSerializableException while attempting to serialize a nested class, we should:

  • Declare the nested class as static
  • Make both the nested class and the enclosing class implement Serializable

6. Conclusion

Dalam artikel ini, kami telah melihat apa itu kelas bersarang dan jenisnya. Kami juga melihat bagaimana penglihatan lapangan dan pengubah akses berbeza di antara pelbagai jenis tersebut.

Seperti biasa, pelaksanaan penuh tutorial ini boleh didapati di GitHub.