Pertanyaan Kelas dalam Jawa dan kelas bertingkat statis


Apa perbedaan utama antara kelas batin dan kelas bertingkat statis di Jawa? Apakah desain / implementasi memainkan peran dalam memilih salah satunya?


1464
2017-09-16 08:22


asal


Jawaban:


Dari Tutorial Java:

Kelas bertingkat dibagi menjadi dua kategori: statis dan non-statis. Kelas bertingkat yang dinyatakan statis disebut sebagai kelas bertingkat statis. Kelas bertingkat non-statik disebut kelas batin.

Kelas bertingkat statis diakses menggunakan nama kelas melampirkan:

OuterClass.StaticNestedClass

Misalnya, untuk membuat objek untuk kelas bertingkat statis, gunakan sintaks ini:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objek yang merupakan contoh dari kelas batin ada dalam sebuah instance dari kelas luar. Pertimbangkan kelas-kelas berikut:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}

Instance dari InnerClass hanya bisa ada di dalam instance OuterClass dan memiliki akses langsung ke metode dan bidang dari instance penutupnya.

Untuk instantiate kelas batin, Anda harus terlebih dahulu instantiate kelas luar. Kemudian, buat objek dalam objek luar dengan sintaks ini:

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

Lihat: Java Tutorial - Kelas Bersarang

Untuk kelengkapan dicatat bahwa ada juga hal seperti itu kelas batin tanpa contoh yang melingkupi:

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

Sini, new A() { ... } adalah kelas batin didefinisikan dalam konteks statis dan tidak memiliki instance penutup.


1480
2017-09-16 08:28



Itu Tutorial Java mengatakan:

Terminologi: Kelas bertingkat adalah   dibagi menjadi dua kategori: statis   dan non-statis. Kelas bertingkat itu   dinyatakan statis hanya disebut   kelas bertingkat statis. Non-statis   kelas bertingkat disebut inner   kelas.

Dalam bahasa umum, istilah "nested" dan "inner" digunakan secara bergantian oleh sebagian besar programmer, tetapi saya akan menggunakan istilah "kelas nested" yang benar yang mencakup bagian dalam dan statis.

Kelas dapat disarangkan ad infinitum, mis. kelas A dapat berisi kelas B yang berisi kelas C yang berisi kelas D, dll. Namun, lebih dari satu tingkat kelas yang bersarang langka, karena umumnya merupakan desain yang buruk.

Ada tiga alasan Anda dapat membuat kelas bertingkat:

  • organisasi: kadang-kadang tampaknya paling masuk akal untuk mengurutkan kelas ke ruang nama kelas lain, terutama ketika tidak akan digunakan dalam konteks lain
  • akses: kelas bertingkat memiliki akses khusus ke variabel / bidang kelas mereka yang mengandung (tepatnya variabel / bidang yang tergantung pada jenis kelas bersarang, baik di dalam atau statis).
  • kenyamanan: harus membuat file baru untuk setiap tipe baru mengganggu, sekali lagi, terutama ketika jenis hanya akan digunakan dalam satu konteks

Ada empat jenis kelas bersarang di Jawa. Singkatnya, 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

Izinkan saya menjelaskan lebih detail.


Kelas Statis

Kelas statis adalah jenis yang paling mudah dipahami karena mereka tidak ada hubungannya dengan contoh kelas yang mengandung.

Kelas statis adalah kelas yang dinyatakan sebagai anggota statis dari kelas lain. Sama seperti anggota statis lainnya, kelas seperti itu benar-benar hanya gantungan pada yang menggunakan kelas yang mengandung sebagai ruang namanya, misalnya kelas Kambing dinyatakan sebagai anggota kelas statis 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 oleh paket. Satu-satunya alasan yang bisa dibayangkan untuk membuat kelas statis adalah kelas semacam itu memiliki akses ke anggota statis pribadi yang berisi kelasnya, tetapi saya menganggap ini sebagai justifikasi yang sangat lemah untuk fitur kelas statis.


Kelas batin

Kelas batin 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 dengan kelas statis, kelas batin dikenal sebagai kualifikasi dengan nama kelas yang berisi, pizza.Rhino.Goat, tetapi di dalam kelas yang mengandung, dapat diketahui dengan nama yang sederhana. Namun, setiap contoh dari kelas batin terkait dengan contoh khusus dari kelas yang mengandung: di atas, Kambing dibuat di jerry, secara implisit terikat pada Badak contoh ini di jerry. Jika tidak, kami membuat yang terkait Badak contoh eksplisit ketika kami memberi contoh Kambing:

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

(Perhatikan Anda mengacu pada tipe batin sebagai adil Kambing aneh baru sintaks: Java menyimpulkan tipe yang mengandung dari badak bagian. Dan ya rhino.Goat baru () akan lebih masuk akal bagi saya juga.)

Jadi, apa yang kita dapatkan ini? Nah, instance kelas batin memiliki akses ke anggota instance dari instance kelas berisi. Anggota contoh yang melampirkan ini disebut di dalam kelas batin melalui hanya nama sederhana mereka, bukan melalui  ini (ini di kelas batin mengacu pada instance kelas internal, bukan instance kelas berisi yang terkait):

public class Rhino {

    private String barry;

    public class Goat {
        public void colin() {
            System.out.println(barry);
        }
    }
}

Di kelas batin, Anda bisa merujuk ini kelas yang mengandung sebagai Rhino.ini, dan Anda bisa menggunakannya ini untuk merujuk anggotanya, misalnya Rhino.this.barry.


Kelas Dalam Lokal

Kelas dalam lokal adalah kelas yang dideklarasikan dalam tubuh suatu metode. Kelas semacam itu hanya diketahui dalam metode yang mengandung, sehingga hanya dapat dipakai dan memiliki anggotanya diakses dalam metode yang mengandung. Keuntungannya adalah bahwa contoh kelas dalam lokal terkait dan dapat mengakses variabel lokal terakhir 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 adalah versi Java yang mentah, versi penutupan terbatas).

Karena kelas dalam lokal bukanlah anggota kelas atau paket, itu tidak dideklarasikan dengan tingkat akses. (Namun, jelaslah, bahwa anggota sendiri memiliki tingkat akses seperti di kelas normal.)

Jika kelas dalam lokal dideklarasikan dalam metode instan, instantiasi kelas batin terkait dengan instance yang dipegang oleh metode yang mengandung ini pada saat pembuatan instance, dan jadi anggota kelas yang mengandung kelas dapat diakses seperti dalam contoh kelas batin. Kelas batin lokal hanya dibuat sederhana melalui namanya, misalnya kelas dalam lokal Kucing digunakan sebagai Kucing baru (), bukan baru ini.Cat () seperti yang Anda harapkan.


Kelas Batin Anonim

Kelas batin anonim adalah cara yang secara sintaktis mudah untuk menulis kelas dalam lokal. Paling umum, kelas dalam lokal hanya dipakai sekali saja setiap kali metode yang mengandung dijalankan. Akan sangat menyenangkan, jika kita dapat menggabungkan definisi kelas dalam lokal dan instantiasinya tunggal menjadi satu bentuk sintaks yang nyaman, dan itu juga akan baik jika kita tidak harus memikirkan nama untuk kelas (semakin tidak bermanfaat nama kode Anda mengandung, semakin baik). Kelas batin anonim memungkinkan kedua hal ini:

new *ParentClassName*(*constructorArgs*) {*members*}

Ini adalah ekspresi yang mengembalikan contoh baru dari kelas tanpa nama yang meluas ParentClassName. Anda tidak dapat menyediakan konstruktor Anda sendiri; lebih tepatnya, satu secara implisit disediakan yang hanya memanggil konstruktor super, sehingga argumen yang diberikan harus sesuai dengan konstruktor super. (Jika induk mengandung beberapa konstruktor, yang paling sederhana "disebut," paling sederhana "sebagaimana ditentukan oleh seperangkat aturan yang agak rumit yang tidak perlu dipusingkan untuk dipelajari secara terperinci - cukup perhatikan apa yang NetBeans atau Eclipse beri tahu Anda.)

Alternatifnya, Anda dapat menentukan antarmuka untuk diterapkan:

new *InterfaceName*() {*members*}

Deklarasi semacam itu menciptakan contoh baru dari kelas tanpa nama yang memperpanjang Objek dan alat InterfaceName. Sekali lagi, Anda tidak dapat menyediakan konstruktor Anda sendiri; dalam kasus ini, Java secara implisit mensuplai konstruktor no-arg, do-nothing (sehingga tidak akan pernah ada argumen konstruktor dalam kasus ini).

Meskipun Anda tidak dapat memberikan kelas anonim konstruktor, Anda masih bisa melakukan pengaturan apa pun yang Anda inginkan menggunakan blok initializer (blok {} ditempatkan di luar metode apa pun).

Jelaslah bahwa kelas batin anonim hanyalah cara yang kurang fleksibel untuk menciptakan kelas dalam lokal dengan satu contoh. Jika Anda ingin kelas dalam lokal yang mengimplementasikan beberapa antarmuka atau yang mengimplementasikan antarmuka sambil memperluas beberapa kelas selain Obyek atau yang menentukan konstruktornya sendiri, Anda terjebak menciptakan kelas internal lokal yang bernama biasa.


524
2017-09-16 09:24



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

Pertama untuk mendapatkan persyaratan dengan benar:

  • Kelas bertingkat adalah kelas yang terdapat di kelas lain pada tingkat kode sumber.
  • Ini statis jika Anda mendeklarasikannya dengan statis pengubah.
  • Kelas bertingkat non-statik disebut kelas dalam. (Saya tinggal dengan kelas bertingkat non-statis.)

Jawaban Martin benar sejauh ini. Namun, pertanyaan sebenarnya adalah: Apa tujuan mendeklarasikan kelas bertingkat statis atau tidak?

Kau gunakan kelas bertingkat statis jika Anda hanya ingin menjaga kelas Anda bersama-sama jika mereka termasuk topikal bersama-sama atau jika kelas bertingkat secara eksklusif digunakan dalam kelas melampirkan. Tidak ada perbedaan semantik antara kelas bertingkat statis dan setiap kelas lainnya.

Kelas bertingkat non-statis adalah binatang yang berbeda. Serupa dengan kelas-kelas dalam anonim, kelas bertingkat seperti itu sebenarnya adalah penutupan. Itu berarti mereka menangkap lingkup sekitarnya dan contoh penutup mereka dan membuatnya dapat diakses. Mungkin sebuah contoh akan memperjelas itu. Lihat rintisan ini dari Kontainer:

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 penampung induk. Menggunakan kelas bertingkat non-statik, ini bekerja tanpa beberapa pekerjaan. Anda dapat mengakses contoh Penampung yang menyertakan dengan sintaks Container.this.

Lebih banyak penjelasan hardcore berikut:

Jika Anda melihat Java bytecodes yang dihasilkan compiler untuk kelas bertingkat (non-statis) 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 compiler membuat bidang tersembunyi Container this$0. Ini diatur dalam konstruktor yang memiliki parameter tambahan tipe Kontainer untuk menentukan instance penutup. Anda tidak dapat melihat parameter ini di sumber tetapi kompilator secara implisit menghasilkannya untuk kelas bertingkat.

Teladan Martin

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

begitu akan dikompilasi ke panggilan sesuatu seperti (dalam bytecodes)

new InnerClass(outerObject)

Demi kelengkapan:

Kelas anonim aku s contoh sempurna dari kelas bertingkat non-statik yang tidak memiliki nama yang dikaitkan dengannya dan tidak dapat dijadikan referensi nantinya.


124
2017-09-16 09:12



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

OverView

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

Perbedaan

Kelas Nonstatic Nested : secara implisit terkait dengan instance penutup kelas yang berisi, ini berarti bahwa dimungkinkan untuk memanggil metode dan variabel akses dari instance penutup. Satu penggunaan umum dari kelas bertingkat non-statis adalah mendefinisikan kelas Adaptor.

Kelas Bertingkat Statis : tidak dapat mengakses instance kelas lampiran dan memanggil metode di atasnya, jadi harus digunakan ketika kelas bertingkat tidak memerlukan akses ke instance dari kelas melampirkan. Penggunaan yang umum dari kelas bertingkat statis adalah mengimplementasikan komponen dari objek luar.

Kesimpulan

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


82
2018-05-27 07:43



Dalam istilah sederhana, kami membutuhkan kelas bertingkat terutama karena Java tidak menyediakan penutup.

Kelas Bersarang adalah kelas yang didefinisikan di dalam tubuh kelas melampirkan lainnya. Mereka terdiri dari dua jenis - statis dan non-statis.

Mereka diperlakukan sebagai anggota kelas melampirkan, maka Anda dapat menentukan salah satu dari empat penentu akses - private, package, protected, public. Kami tidak memiliki kemewahan ini dengan kelas-kelas top-level, yang hanya bisa dideklarasikan public atau paket-pribadi.

Kelas-kelas batin alias kelas-kelas Non-stack memiliki akses ke anggota lain dari kelas atas, bahkan jika mereka dinyatakan privat sementara kelas bertingkat Static tidak memiliki akses ke anggota lain dari kelas atas.

public class OuterClass {
    public static class Inner1 {
    }
    public class Inner2 {
    }
}

Inner1 adalah kelas batin statis kami dan Inner2 adalah kelas batin kita yang tidak statis. Perbedaan utama di antara mereka, Anda tidak dapat membuat Inner2 contoh tanpa Outer di mana Anda dapat membuat Inner1 objek secara mandiri.

Kapan kamu akan menggunakan kelas dalam?

Pikirkan situasi di mana Class A dan Class B yang terkait, Class B perlu akses Class A anggota, dan Class B hanya terkait dengan Class A. Kelas batin masuk ke dalam gambar.

Untuk membuat instance kelas batin, 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 statis statis?

Anda akan mendefinisikan kelas inti statis ketika Anda tahu bahwa itu tidak memiliki hubungan dengan contoh kelas melampirkan / kelas atas. Jika kelas batin Anda tidak menggunakan metode atau bidang kelas luar, itu hanya membuang-buang ruang, jadi membuatnya statis.

Misalnya, untuk membuat objek untuk kelas bertingkat statis, gunakan sintaks ini:

OuterClass.Inner1 nestedObject = new OuterClass.Inner1();

Keuntungan dari kelas bertingkat statis adalah bahwa ia tidak memerlukan objek kelas yang berisi / kelas atas untuk bekerja. Ini dapat membantu Anda mengurangi jumlah objek yang dibuat aplikasi Anda saat runtime.


30
2017-10-17 22:35



Saya pikir, konvensi yang umumnya diikuti adalah ini:

  • kelas statis dalam kelas tingkat atas adalah a kelas bertingkat
  • kelas tidak statis dalam kelas tingkat atas adalah a kelas batin, yang selanjutnya memiliki dua bentuk lagi:
    • kelas lokal - kelas bernama dideklarasikan di dalam blok seperti metode atau badan konstruktor
    • kelas anonim - kelas tanpa nama yang instancenya dibuat dalam ekspresi dan pernyataan

Namun, beberapa lainnya poin untuk diingat adalah:

  • Kelas tingkat atas dan kelas bertingkat statis secara semantik sama kecuali bahwa dalam kasus kelas bertingkat statis dapat membuat referensi statis ke bidang / metode statis privat kelas Luar [induk] dan sebaliknya.

  • Kelas-kelas batin memiliki akses ke variabel instan dari instance penutup kelas Outer [parent]. Namun, tidak semua kelas dalam telah menyertakan contoh, 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 klausul lebih lanjut untuk memperluas kelas lain atau mengimplementasikan antarmuka lainnya. Begitu,

    • new YourClass(){};cara class [Anonymous] extends YourClass {}
    • new YourInterface(){};   cara class [Anonymous] implements YourInterface {}

Saya merasa bahwa pertanyaan besar yang tetap terbuka yang mana yang akan digunakan dan kapan? Nah itu sebagian besar tergantung pada skenario apa yang Anda hadapi tetapi membaca balasan yang diberikan oleh @jrudolph dapat membantu Anda membuat beberapa keputusan.


24
2017-12-16 11:38



Berikut adalah perbedaan utama dan persamaan antara kelas dalam Jawa dan kelas bertingkat statis.

Semoga itu membantu!

Kelas batin

  • Dapat mengakses ke kelas luar baik instance maupun statis metode dan bidang
  • Terkait dengan instance dari kelas melampirkan jadi untuk instantiate pertama perlu sebuah instance dari kelas luar (catatan baru tempat kata kunci):

    Outerclass.InnerClass innerObject = outerObject.new Innerclass();
    
  • Tidak bisa mendefinisikan apa saja anggota statis diri

  • Tidak bisa memiliki Kelas atau Antarmuka pernyataan

Kelas bersarang statis

  • Tidak dapat mengakses kelas luar contoh metode atau bidang

  • Tidak terkait dengan instance mana pun yang melampirkan kelas Jadi untuk instantiate:

    OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
    

Kesamaan

  • Kedua Kelas batin dapat mengakses bahkan bidang dan metode pribadi dari kelas luar
  • Juga Kelas luar memiliki akses ke bidang dan metode pribadi dari kelas batin
  • Kedua kelas dapat memiliki pengubah akses privat, terlindungi atau umum

Mengapa Menggunakan Kelas Bersarang?

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 tersebut dan menjaga keduanya bersama. Bersarang seperti "kelas pembantu" membuat paket mereka lebih ramping.

  • Ini meningkatkan enkapsulasi: Pertimbangkan dua kelas tingkat atas, A dan B, di mana B memerlukan akses ke anggota A yang dinyatakan akan dinyatakan pribadi. Dengan menyembunyikan kelas B dalam kelas A, anggota A dapat dinyatakan sebagai pribadi dan B dapat mengaksesnya. Selain itu, B sendiri dapat disembunyikan dari dunia luar.

  • Ini dapat mengarah pada kode yang lebih mudah dibaca dan dipelihara: Bersarang kelas kecil di kelas top-level menempatkan kode lebih dekat ke tempat itu digunakan.


23
2017-12-31 20:53



Kelas bersarang: kelas di dalam kelas

Jenis:

  1. Kelas bersarang statis
  2. Kelas bertingkat non-statis [Kelas batin]

Perbedaan:

Kelas bertingkat non-statis [Kelas batin]

Di dalam kelas non-statik, objek kelas dalam ada di dalam objek dari kelas luar. Sehingga data anggota kelas luar dapat diakses oleh kelas batin. Jadi untuk membuat objek kelas batin kita harus membuat objek dari kelas luar terlebih dahulu.

outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass(); 

Kelas bersarang statis

Dalam objek kelas bertingkat statis dari kelas batin tidak perlu objek 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 dalam berikut

  outerclass.nestedclass.x;  i.e. System.out.prinltn( outerclass.nestedclass.x);

13
2018-04-04 10:14



Instance dari kelas batin dibuat ketika instance dari kelas luar dibuat. Oleh karena itu anggota dan metode kelas batin memiliki akses ke anggota dan metode dari instance (objek) dari kelas luar. Ketika contoh kelas luar keluar dari ruang lingkup, juga contoh kelas batin tidak ada lagi.

Kelas bertingkat statis tidak memiliki contoh konkret. Ini hanya dimuat ketika digunakan untuk pertama kalinya (sama seperti metode statis). Ini adalah entitas yang benar-benar independen, yang metode dan variabelnya tidak memiliki akses ke instance kelas luar.

Kelas bertingkat statis tidak digabungkan dengan objek luar, mereka lebih cepat, dan mereka tidak mengambil tumpukan / memori stack, karena tidak perlu membuat instance dari kelas tersebut. Oleh karena itu aturan praktisnya adalah mencoba mendefinisikan kelas bertingkat statis, dengan ruang lingkup terbatas mungkin (private> = class> = protected> = publik), dan kemudian mengkonversinya ke kelas dalam (dengan menghapus pengenal "statis") dan mengendurkan ruang lingkup, jika itu benar-benar diperlukan.


11
2017-09-16 08:58



Ada kehalusan tentang penggunaan kelas statis bertingkat yang mungkin berguna dalam situasi tertentu.

Sedangkan atribut statis mendapatkan instantiated sebelum kelas mendapatkan instantiated melalui konstruktornya, atribut statis di dalam kelas statis nested tampaknya tidak mendapatkan instantiated sampai setelah konstruktor kelas akan dipanggil, atau setidaknya tidak sampai setelah atribut yang pertama direferensikan, bahkan jika mereka ditandai sebagai 'akhir'.

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 'bersarang' dan 'innerItem' keduanya dinyatakan sebagai 'akhir statis'. pengaturan dari nested.innerItem tidak terjadi sampai setelah kelas dipakai (atau setidaknya tidak sampai setelah item statis bersarang dirujuk pertama kali), seperti yang Anda lihat sendiri dengan berkomentar dan tidak menyebutkan baris yang saya rujuk, di atas. Hal yang sama tidak berlaku benar untuk 'outerItem'.

Setidaknya inilah yang saya lihat di Java 6.0.


10
2018-03-26 12:38