Java - Tidak ada instance tertutup dari tipe Foo yang dapat diakses

314

Saya memiliki kode berikut:

class Hello {
    class Thing {
        public int size;

        Thing() {
            size = 0;
        }
    }

    public static void main(String[] args) {
        Thing thing1 = new Thing();
        System.out.println("Hello, World!");
    }
}

Saya tahu Thingtidak melakukan apa-apa, tetapi program Hello, World saya dapat dikompilasi tanpa itu. Hanya kelas saya yang didefinisikan yang gagal pada saya.

Dan itu menolak untuk dikompilasi. Saya mendapatkan No enclosing instance of type Hello is accessible."pada baris yang menciptakan Hal baru. Saya menebak:

  1. Saya memiliki masalah tingkat sistem (baik di DrJava atau Java install saya) atau
  2. Saya memiliki beberapa kesalahpahaman dasar tentang bagaimana membangun program kerja di java.

Ada ide?

coolpapa
sumber
kemungkinan duplikat kelas dalam Java dan kelas bersarang statis
Strelok

Jawaban:

483

static class Thing akan membuat program Anda berfungsi.

Seperti itu, Anda punya Thingsebagai kelas dalam, yang (menurut definisi) dikaitkan dengan contoh tertentu Hello(bahkan jika itu tidak pernah menggunakan atau merujuk padanya), yang berarti kesalahan untuk mengatakan new Thing();tanpa memiliki Hellocontoh khusus di cakupan.

Jika Anda mendeklarasikannya sebagai kelas statis, maka itu adalah kelas "bersarang", yang tidak memerlukan Helloinstance tertentu .

jacobm
sumber
Apakah ini juga berarti bahwa jika saya instantiate outer class, non-static inner classitu akan dibuat juga bahkan jika saya tidak menggunakannya di mana saja?
mr5
Tidak. Setiap objek dari kelas dalam harus memiliki orang tua, tetapi orang tua dapat memiliki jumlah anak termasuk 0.
jacobm
92

Anda telah mendeklarasikan kelas Thingsebagai kelas dalam yang tidak statis. Itu berarti harus dikaitkan dengan instance Hellokelas.

Dalam kode Anda, Anda mencoba membuat instance dari Thingkonteks statis. Itulah yang dikeluhkan kompiler.

Ada beberapa solusi yang mungkin. Solusi mana yang digunakan tergantung pada apa yang ingin Anda capai.

  • Pindahkan Thingkeluar dari Hellokelas.

  • Ubah Thingmenjadi statickelas bersarang.

    static class Thing
  • Buat sebuah contoh dari Hellosebelum membuat sebuah instance dari Thing.

    public static void main(String[] args)
    {
        Hello h = new Hello();
        Thing thing1 = h.new Thing(); // hope this syntax is right, typing on the fly :P
    }

Solusi terakhir ( kelas bersarang non-statis ) akan wajib jika instance Thingbergantung pada instance Hellomenjadi bermakna. Misalnya, jika kita punya:

public class Hello {
    public int enormous;

    public Hello(int n) {
        enormous = n;
    }

    public class Thing {
        public int size;

        public Thing(int m) {
            if (m > enormous)
                size = enormous;
            else
                size = m;
        }
    }
    ...
}

setiap upaya mentah untuk membuat objek kelas Thing, seperti pada:

Thing t = new Thing(31);

akan bermasalah, karena tidak akan ada enormousnilai yang jelas untuk menguji 31 ​​terhadapnya. Sebuah instance hdari Hellokelas luar diperlukan untuk memberikan h.enormousnilai ini :

...
Hello h = new Hello(30);
...
Thing t = h.new Thing(31);
...

Karena itu tidak berarti Thingjika tidak memiliki Hello.

Untuk informasi lebih lanjut tentang kelas bersarang / dalam: Kelas Bertingkat (Tutorial Java)

helloworld922
sumber
Jawaban Anda komprehensif dan sintetis. Sekalipun terasa aneh (setidaknya bagi saya), sintaksnya benar.
boumbh
Jika ada yang masih mendapatkan kesalahan, sintaks Thing thing1 <<HelloInstantiation>>.new Thing()adalah kuncinya. Saya menghabiskan beberapa menit bingung menggunakan sintaks Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou
1
@ skia.heliou Terima kasih! Saya membuat kelas pembantu dan variabel statis (atau bahkan kelas) tidak hanya menghilangkan ruang lingkup, tetapi mereka sering tidak efisien. Perlu memberikan argumen runtime membuatnya repot untuk menggunakan metode utama. Ini semua yang saya butuhkan dan persis apa yang saya cari.
Abandoned Cart
25

Yah ... begitu banyak jawaban bagus tetapi saya ingin menambahkan lebih banyak tentang itu. Pandangan singkat tentang kelas dalam di Jawa-Jawa memungkinkan kita untuk mendefinisikan kelas dalam kelas lain dan Mampu kelas sarang dengan cara ini memiliki keuntungan tertentu:

  1. Itu dapat menyembunyikan (Ini meningkatkan enkapsulasi) kelas dari kelas lain - terutama relevan jika kelas hanya digunakan oleh kelas yang terkandung di dalamnya. Dalam hal ini tidak perlu bagi dunia luar untuk mengetahuinya.

  2. Ini dapat membuat kode lebih mudah dikelola karena kelas secara logis dikelompokkan bersama di mana mereka dibutuhkan.

  3. Kelas dalam memiliki akses ke variabel instan dan metode kelas yang mengandungnya.

Kami memiliki tiga jenis Inner Classes

  1. Batin lokal
  2. Kelas Batin Statis
  3. Kelas Batin Anonim

Beberapa poin penting yang harus diingat

  • Kita membutuhkan objek kelas untuk mengakses Kelas Dalam Lokal di mana itu ada.
  • Static Inner Class bisa diakses langsung sama seperti metode statis lainnya dari kelas yang sama di mana ia ada.
  • Kelas Batin Anonim tidak terlihat oleh dunia luar maupun metode atau kelas lain dari kelas yang sama (di mana ia ada) dan digunakan pada titik di mana ia dinyatakan.

Mari kita coba melihat konsep di atas secara praktis_

public class MyInnerClass {

public static void main(String args[]) throws InterruptedException {
    // direct access to inner class method
    new MyInnerClass.StaticInnerClass().staticInnerClassMethod();

    // static inner class reference object
    StaticInnerClass staticInnerclass = new StaticInnerClass();
    staticInnerclass.staticInnerClassMethod();

    // access local inner class
    LocalInnerClass localInnerClass = new MyInnerClass().new LocalInnerClass();
    localInnerClass.localInnerClassMethod();

    /*
     * Pay attention to the opening curly braces and the fact that there's a
     * semicolon at the very end, once the anonymous class is created:
     */
    /*
     AnonymousClass anonymousClass = new AnonymousClass() {
         // your code goes here...

     };*/
 }

// static inner class
static class StaticInnerClass {
    public void staticInnerClassMethod() {
        System.out.println("Hay... from Static Inner class!");
    }
}

// local inner class
class LocalInnerClass {
    public void localInnerClassMethod() {
        System.out.println("Hay... from local Inner class!");
    }
 }

}

Saya harap ini akan membantu semua orang. Silakan merujuk lebih lanjut

Rupesh Yadav
sumber
Perbaikan yang disarankan: beri nama MyOuterClass kelas pertama, hapus komentar dari sekitar AnonymousClass.
Noumenon
9

Thingadalah kelas dalam dengan koneksi otomatis ke instance dari Hello. Anda mendapatkan kesalahan kompilasi karena tidak ada instance Hellountuk dilampirkan. Anda dapat memperbaikinya dengan paling mudah dengan mengubahnya ke kelas bersarang statis yang tidak memiliki koneksi:

static class Thing
David Harkness
sumber
9

Mari kita memahaminya dengan contoh sederhana berikut ini. Ini terjadi karena ini adalah NASS-STATIC INNER CLASS. Anda harus membutuhkan instance dari kelas luar.

 public class PQ {

    public static void main(String[] args) {

        // create dog object here
        Dog dog = new PQ().new Dog();
        //OR
        PQ pq = new PQ();
        Dog dog1 = pq.new Dog();
    }

    abstract class Animal {
        abstract void checkup();
    }

    class Dog extends Animal {
        @Override
        void checkup() {
            System.out.println("Dog checkup");

        }
    }

    class Cat extends Animal {
        @Override
        void checkup() {
            System.out.println("Cat Checkup");

        }
    }
}
AZ_
sumber