Java - Aucune instance englobante de type Foo n'est accessible

314

J'ai le code suivant:

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

Je sais que Thingcela ne fait rien, mais mon programme Hello, World se compile très bien sans cela. Ce ne sont que mes classes définies qui échouent sur moi.

Et il refuse de compiler. J'arrive No enclosing instance of type Hello is accessible."à la ligne qui crée une nouvelle chose. Je suppose que non plus:

  1. J'ai des problèmes au niveau du système (soit dans DrJava ou mon installation Java) ou
  2. J'ai une mauvaise compréhension de base de la façon de construire un programme de travail en Java.

Des idées?

coolpapa
la source

Réponses:

483

static class Thing fera fonctionner votre programme.

En l'état, vous avez Thingune classe interne, qui (par définition) est associée à une instance particulière de Hello(même si elle ne l'utilise jamais ou n'y fait jamais référence), ce qui signifie que c'est une erreur à dire new Thing();sans avoir une Helloinstance particulière dans portée.

Si vous la déclarez plutôt comme une classe statique, alors c'est une classe "imbriquée", qui n'a pas besoin d'une Helloinstance particulière .

jacobm
la source
Cela signifie-t-il également que si j'instancie le outer class, le non-static inner classserait également créé même si je ne l'utilise nulle part?
mr5
Non. Chaque objet d'une classe interne doit avoir un parent, mais un parent peut avoir n'importe quel nombre d'enfants, y compris 0.
jacobm
92

Vous avez déclaré la classe Thingcomme classe interne non statique. Cela signifie qu'il doit être associé à une instance de la Helloclasse.

Dans votre code, vous essayez de créer une instance de à Thingpartir d'un contexte statique. C'est de cela que se plaint le compilateur.

Il existe quelques solutions possibles. La solution à utiliser dépend de ce que vous souhaitez réaliser.

  • Déplacer Thingde la Helloclasse.

  • Changez Thingpour être une staticclasse imbriquée.

    static class Thing
  • Créez une instance de Helloavant de créer une instance de 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
    }

La dernière solution (une classe imbriquée non statique ) serait obligatoire si une instance de Thingdépendait d'une instance de Hellopour être significative. Par exemple, si nous avions:

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

toute tentative brute de créer un objet de classe Thing, comme dans:

Thing t = new Thing(31);

serait problématique, car il n'y aurait pas de enormousvaleur évidente à comparer avec 31. Une instance hde la Helloclasse externe est nécessaire pour fournir cette h.enormousvaleur:

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

Parce que cela ne signifie pas un Things'il n'a pas Hello.

Pour plus d'informations sur les classes imbriquées / internes: classes imbriquées (didacticiels Java)

helloworld922
la source
Votre réponse est à la fois complète et synthétique. Même si cela semble étrange (du moins pour moi), la syntaxe est correcte.
boumbh
Si quelqu'un a encore des erreurs, la syntaxe Thing thing1 <<HelloInstantiation>>.new Thing()est la clé. J'ai passé quelques minutes confus en utilisant la syntaxe Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou
1
@ skia.heliou Merci! Je faisais une classe d'assistance et des variables statiques (ou même des classes) non seulement éliminent la portée, mais elles sont souvent inefficaces. La nécessité de fournir des arguments d'exécution rend la peine d'utiliser une méthode principale. C'était tout ce dont j'avais besoin et exactement ce que je cherchais.
Panier abandonné
25

Eh bien ... tant de bonnes réponses, mais je veux en ajouter plus. Un bref aperçu de la classe interne en Java - Java nous permet de définir une classe dans une autre classe et pouvoir imbriquer des classes de cette manière présente certains avantages:

  1. Il peut cacher (il augmente l'encapsulation) la classe des autres classes - particulièrement pertinent si la classe n'est utilisée que par la classe dans laquelle elle est contenue. Dans ce cas, le monde extérieur n'a pas besoin de le savoir.

  2. Cela peut rendre le code plus facile à maintenir car les classes sont logiquement regroupées autour de l'endroit où elles sont nécessaires.

  3. La classe interne a accès aux variables d'instance et aux méthodes de sa classe conteneur .

Nous avons principalement trois types de Inner Classes

  1. Intérieur local
  2. Classe intérieure statique
  3. Classe intérieure anonyme

Quelques points importants à retenir

  • Nous avons besoin d'un objet de classe pour accéder à la classe interne locale dans laquelle il existe.
  • La classe interne statique est directement accessible comme comme toute autre méthode statique de la même classe dans laquelle elle existe.
  • La classe intérieure anonyme n'est pas visible pour le monde extérieur ainsi que pour les autres méthodes ou classes de la même classe (dans laquelle elle existe) et elle est utilisée au point où elle est déclarée.

Essayons de voir les concepts ci-dessus pratiquement_

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

}

J'espère que cela aidera tout le monde. Veuillez vous référer pour plus

Rupesh Yadav
la source
Améliorations suggérées: nommez la première classe MyOuterClass, supprimez les commentaires de la classe AnonymousClass.
Noumenon
9

Thingest une classe interne avec une connexion automatique à une instance de Hello. Vous obtenez une erreur de compilation car il n'y a pas d'instance Helloà laquelle attacher. Vous pouvez le corriger plus facilement en le changeant en une classe imbriquée statique qui n'a pas de connexion:

static class Thing
David Harkness
la source
9

Permet de le comprendre avec l'exemple simple suivant. Cela se produit car il s'agit d'une CLASSE INTERNE NON STATIQUE. Vous devez avoir besoin de l'instance de classe externe.

 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_
la source