Java - Auf keine einschließende Instanz vom Typ Foo kann zugegriffen werden

314

Ich habe folgenden Code:

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

Ich weiß, Thingmacht nichts, aber mein Hello, World-Programm lässt sich ohne es gut kompilieren. Es sind nur meine definierten Klassen, die bei mir versagen.

Und es weigert sich zu kompilieren. Ich komme No enclosing instance of type Hello is accessible."an die Linie, die eine neue Sache schafft. Ich vermute auch:

  1. Ich habe Probleme auf Systemebene (entweder in DrJava oder in meiner Java-Installation) oder
  2. Ich habe einige grundlegende Missverständnisse darüber, wie man ein Arbeitsprogramm in Java erstellt.

Irgendwelche Ideen?

coolpapa
quelle

Antworten:

483

static class Thing wird Ihr Programm zum Laufen bringen.

So wie es ist, haben Sie Thingeine innere Klasse, die (per Definition) einer bestimmten Instanz von zugeordnet ist Hello(auch wenn sie diese nie verwendet oder darauf verweist), was bedeutet, dass es ein Fehler ist, zu sagen, new Thing();ohne eine bestimmte HelloInstanz zu haben Umfang.

Wenn Sie es stattdessen als statische Klasse deklarieren, handelt es sich um eine "verschachtelte" Klasse, für die keine bestimmte HelloInstanz erforderlich ist .

Jacobm
quelle
Bedeutet dies auch, dass, wenn ich das instanziiere outer class, das non-static inner classauch erstellt wird, selbst wenn ich es nirgendwo benutze?
Mr5
Nein. Jedes Objekt einer inneren Klasse muss einen Elternteil haben, aber ein Elternteil kann eine beliebige Anzahl von Kindern haben, einschließlich 0.
jacobm
92

Sie haben die Klasse Thingals nicht statische innere Klasse deklariert . Das heißt, es muss einer Instanz der HelloKlasse zugeordnet sein.

In Ihrem Code versuchen Sie, eine Instanz von Thingaus einem statischen Kontext zu erstellen . Darüber beschwert sich der Compiler.

Es gibt einige mögliche Lösungen. Welche Lösung verwendet werden soll, hängt davon ab, was Sie erreichen möchten.

  • Verlasse Thingdie HelloKlasse.

  • Ändern Sie Thing, um eine staticverschachtelte Klasse zu sein.

    static class Thing
  • Erstellen Sie eine Instanz von, Hellobevor Sie eine Instanz von erstellen 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
    }
    

Die letzte Lösung (eine nicht statisch verschachtelte Klasse) wäre obligatorisch, wenn eine Instanz von Thingeiner Instanz abhängt Hello, um sinnvoll zu sein. Zum Beispiel, wenn wir hätten:

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

Jeder rohe Versuch, ein Klassenobjekt zu erstellen Thing, wie in:

Thing t = new Thing(31);

wäre problematisch, da es keinen offensichtlichen enormousWert gäbe , 31 dagegen zu testen. Eine Instanz hder Helloäußeren Klasse ist erforderlich, um diesen h.enormousWert bereitzustellen :

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

Weil es nicht bedeutet, Thingwenn es kein hat Hello.

Weitere Informationen zu verschachtelten / inneren Klassen: Verschachtelte Klassen (Die Java-Tutorials)

helloworld922
quelle
Ihre Antwort ist sowohl umfassend als auch synthetisch. Auch wenn es sich seltsam anfühlt (zumindest für mich), ist die Syntax korrekt.
Boumbh
Wenn immer noch Fehler auftreten, ist die Syntax Thing thing1 <<HelloInstantiation>>.new Thing()der Schlüssel. Ich war ein paar Minuten verwirrt mit der Syntax Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou
1
@ skia.heliou Danke! Ich habe eine Hilfsklasse erstellt, und statische Variablen (oder sogar Klassen) eliminieren nicht nur den Gültigkeitsbereich, sondern sind häufig ineffizient. Wenn Laufzeitargumente angegeben werden müssen, ist es schwierig, eine Hauptmethode zu verwenden. Das war alles was ich brauchte und genau das was ich suchte.
Verlassener Wagen
25

Nun ... so viele gute Antworten, aber ich möchte noch mehr hinzufügen. Ein kurzer Blick auf die innere Klasse in Java-Java ermöglicht es uns, eine Klasse innerhalb einer anderen Klasse zu definieren. Die Möglichkeit, Klassen auf diese Weise zu verschachteln, hat bestimmte Vorteile:

  1. Es kann die Klasse vor anderen Klassen verbergen (es erhöht die Kapselung) - besonders relevant, wenn die Klasse nur von der Klasse verwendet wird, in der sie enthalten ist. In diesem Fall muss die Außenwelt nichts darüber wissen.

  2. Dadurch kann Code besser gewartet werden, da die Klassen logisch dort gruppiert werden, wo sie benötigt werden.

  3. Die innere Klasse hat Zugriff auf die Instanzvariablen und Methoden ihrer enthaltenden Klasse.

Wir haben hauptsächlich drei Arten von Inner Classes

  1. Lokale innere
  2. Statische innere Klasse
  3. Anonyme innere Klasse

Einige der wichtigsten Punkte, an die Sie sich erinnern sollten

  • Wir benötigen ein Klassenobjekt, um auf die lokale innere Klasse zuzugreifen, in der es existiert.
  • Der Zugriff auf die statische innere Klasse erfolgt wie bei jeder anderen statischen Methode derselben Klasse, in der sie vorhanden ist, direkt.
  • Anonyme innere Klassen sind sowohl für die Außenwelt als auch für die anderen Methoden oder Klassen derselben Klasse (in der sie existieren) nicht sichtbar und werden an dem Punkt verwendet, an dem sie deklariert sind.

Versuchen wir, die obigen Konzepte praktisch zu sehen.

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

}

Ich hoffe, das wird allen helfen. Bitte beziehen Sie sich auf mehr

Rupesh Yadav
quelle
Verbesserungsvorschläge: Benennen Sie die MyOuterClass der ersten Klasse und entfernen Sie die Kommentare aus AnonymousClass.
Noumenon
9

Thingist eine innere Klasse mit einer automatischen Verbindung zu einer Instanz von Hello. Sie erhalten einen Kompilierungsfehler, da keine Instanz Hellozum Anhängen vorhanden ist. Sie können es am einfachsten beheben, indem Sie es in eine statisch verschachtelte Klasse ändern, die keine Verbindung hat:

static class Thing
David Harkness
quelle
9

Verstehen wir es anhand des folgenden einfachen Beispiels. Dies geschieht, weil dies eine NICHT STATISCHE INNERE KLASSE ist. Sie sollten die Instanz der äußeren Klasse benötigen.

 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_
quelle