Java - Nie jest dostępna żadna instancja załączająca typu Foo


314

Mam następujący kod:

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

Wiem, Thingże nic nie robi, ale mój program Hello, World dobrze się bez niego kompiluje. Tylko moje określone klasy zawodzą na mnie.

I odmawia kompilacji. Wchodzę No enclosing instance of type Hello is accessible."na linię, która tworzy nową Rzecz. Zgaduję albo:

  1. Mam problemy na poziomie systemu (w DrJava lub mojej instalacji Java) lub
  2. Mam pewne podstawowe nieporozumienie, jak zbudować działający program w Javie.

Jakieś pomysły?


Odpowiedzi:


483

static class Thing sprawi, że twój program będzie działał.

W tej chwili masz Thingjako wewnętrzną klasę, która (z definicji) jest powiązana z konkretnym wystąpieniem Hello(nawet jeśli nigdy nie używa lub nie odnosi się do niego), co oznacza, że ​​mówienie o błędzie new Thing();bez określonegoHello wystąpienia zakres.

Jeśli zamiast tego zadeklarujesz ją jako klasę statyczną, to będzie to klasa „zagnieżdżona”, która nie potrzebuje konkretnej Helloinstancji.


Czy to oznacza również, że jeśli utworzę instancję outer class, non-static inner classzostanie ona utworzona, nawet jeśli nigdzie jej nie użyję?
mr5

Nie. Każdy obiekt klasy wewnętrznej musi mieć rodzica, ale rodzic może mieć dowolną liczbę dzieci, w tym 0.
jacobm,

92

Zadeklarowałeś klasę Thingjako niestatyczną klasę wewnętrzną. Oznacza to, że musi być powiązany z instancjąHello klasy.

W swoim kodzie próbujesz utworzyć instancję Thing z kontekstu statycznego. Na to narzeka kompilator.

Istnieje kilka możliwych rozwiązań. Wybór rozwiązania zależy od tego, co chcesz osiągnąć.

  • Wyjdź Thingz Helloklasy.

  • Zmień Thingsię na staticklasę zagnieżdżoną.

    static class Thing
  • Tworzenie instancji z Helloprzed utworzeniem instancji 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
    }

Ostatnie rozwiązanie ( niestatyczna klasa zagnieżdżona) byłoby obowiązkowe, gdyby jakakolwiek instancja Thingzależała od instancji, Helloaby była znacząca. Na przykład, gdybyśmy mieli:

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

każda surowa próba stworzenia obiektu klasy Thing, jak w:

Thing t = new Thing(31);

byłoby problematyczne, ponieważ nie byłoby oczywistej enormouswartości, aby przetestować 31 z nim. Wystąpienie hw Hellozewnętrznej klasy jest to konieczne, aby zapewnić to h.enormouswartości:

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

Ponieważ to nie znaczy, Thingjeśli nie ma Hello.

Aby uzyskać więcej informacji na temat klas zagnieżdżonych / wewnętrznych: Zagnieżdżone klasy (samouczki Java)


Twoja odpowiedź jest wyczerpująca i syntetyczna. Nawet jeśli wydaje mi się to dziwne (przynajmniej dla mnie), składnia jest poprawna.
boumbh

Jeśli ktoś nadal otrzymuje błędy, Thing thing1 <<HelloInstantiation>>.new Thing()kluczem jest składnia . Spędziłem kilka minut zdezorientowany przy użyciu składni Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou

1
@ skia.heliou Dzięki! Tworzyłem klasę pomocniczą, a zmienne statyczne (a nawet klasy) nie tylko eliminowały zakres, ale często były nieefektywne. Konieczność podania argumentów środowiska wykonawczego sprawia, że ​​kłopotanie się z użyciem głównej metody jest niemożliwe. To było wszystko, czego potrzebowałem i dokładnie to, co chciałem znaleźć.
Opuszczony

25

Cóż ... tyle dobrych odpowiedzi, ale chcę dodać więcej. Krótkie spojrzenie na klasę wewnętrzną w Javie - Java pozwala nam zdefiniować klasę w innej klasie, a możliwość zagnieżdżania klas w ten sposób ma pewne zalety:

  1. Może ukrywać (zwiększa enkapsulację) klasę przed innymi klasami - szczególnie istotne, jeśli klasa jest używana tylko przez klasę, w której jest zawarta. W takim przypadku świat zewnętrzny nie musi o tym wiedzieć.

  2. Może sprawić, że kod będzie łatwiejszy w utrzymaniu, ponieważ klasy są logicznie pogrupowane wokół miejsca, w którym są potrzebne.

  3. Klasa wewnętrzna ma dostęp do zmiennych instancji i metod zawartych w niej klasy.

Mamy głównie trzy rodzaje Inner Classes

  1. Lokalny wewnętrzny
  2. Statyczna klasa wewnętrzna
  3. Anonimowa klasa wewnętrzna

Niektóre ważne punkty, o których należy pamiętać

  • Potrzebujemy obiektu klasy, aby uzyskać dostęp do lokalnej klasy wewnętrznej, w której on istnieje.
  • Statyczna klasa wewnętrzna jest dostępna bezpośrednio tak samo, jak każda inna metoda statyczna tej samej klasy, w której istnieje.
  • Anonimowa klasa wewnętrzna nie jest widoczna dla świata zewnętrznego, jak również dla innych metod lub klas tej samej klasy (w której istnieje) i jest używana w punkcie, w którym została zadeklarowana.

Spróbujmy zobaczyć powyższe koncepcje praktycznie_

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

}

Mam nadzieję, że to pomoże wszystkim. Proszę odnieść się do więcej


Sugerowane ulepszenia: nazwij MyOuterClass pierwszej klasy, usuń komentarze z AnonymousClass.
Noumenon


9

Zrozumiemy to za pomocą następującego prostego przykładu. Dzieje się tak, ponieważ jest to NIERSTATYCZNA KLASA WEWNĘTRZNA. Potrzebujesz instancji klasy zewnętrznej.

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

        }
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.