Java - нет включающего экземпляра типа Foo - PullRequest
294 голосов
/ 05 марта 2012

У меня есть следующий код:

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

Я знаю, Thing ничего не делает, но моя программа Hello, World прекрасно компилируется без нее. Только мои определенные классы проваливаются на мне.

И он отказывается компилировать. Я получаю No enclosing instance of type Hello is accessible." на линии, которая создает новую вещь. Я предполагаю либо:

  1. У меня проблемы на уровне системы (либо в DrJava, либо в моей установке Java), либо
  2. У меня есть некоторые базовые недоразумения о том, как создать рабочую программу в Java.

Есть идеи?

Ответы [ 5 ]

452 голосов
/ 05 марта 2012

static class Thing заставит вашу программу работать.

Как таковой, у вас есть Thing как внутренний класс, который (по определению) связан с конкретным экземпляром Hello (даже если он никогда не использует или не ссылается на него), что означает, что было бы ошибкой сказать new Thing(); без указания конкретного экземпляра Hello в области видимости.

Если вместо этого вы объявите его как статический класс, то это «вложенный» класс, который не нуждается в конкретном Hello экземпляре.

85 голосов
/ 05 марта 2012

Вы объявили класс Thing как нестатический внутренний класс.Это означает, что он должен быть связан с экземпляром класса Hello.

В вашем коде вы пытаетесь создать экземпляр Thing из статического контекста.Это то, на что жалуется компилятор.

Есть несколько возможных решений.Какое решение использовать, зависит от того, чего вы хотите достичь.

  • Вывести Thing из класса Hello.

  • Изменить Thing быть вложенным классом static.

    static class Thing
    
  • Создать экземпляр из Hello перед созданием экземпляра 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
    }
    

Последнее решение ( нестатический вложенный класс) будет обязательным, если любой экземпляр Thing зависит от экземпляра Hello, который будетосмысленный.Например, если бы у нас было:

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

любая грубая попытка создать объект класса Thing, например:

Thing t = new Thing(31);

, была бы проблематичной, посколькубыть очевидным enormous значением для проверки 31 против него.Экземпляр h внешнего класса Hello необходим для предоставления этого значения h.enormous:

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

Поскольку это не означает Thing, если у него нет Hello.

Для получения дополнительной информации о вложенных / внутренних классах: Вложенные классы (Учебные руководства по Java)

24 голосов
/ 03 октября 2013

Ну ... так много хороших ответов, но я хочу добавить еще.Краткий обзор Внутреннего класса в Java-Java позволяет нам определять класс в другом классе, и возможность вложения классов таким образом имеет определенные преимущества:

  1. Может скрыть(Это увеличивает инкапсуляцию) класс из других классов - особенно актуально, если этот класс используется только тем классом, в котором он содержится.В этом случае внешний мир не должен знать об этом.

  2. Это может сделать код более понятным , поскольку классы логически сгруппированы вокруг того места, где они

  3. Внутренний класс имеет доступ к переменным экземпляра и методам содержащего его класса.

Мыимеют в основном три типа Inner Classes

  1. локальный внутренний
  2. статический внутренний класс
  3. анонимный внутренний класс

Некоторые важные моменты, которые следует запомнить

  • Нам нужен объект класса для доступа к локальному внутреннему классу, в котором он существует.
  • Статический внутренний класс getпрямой доступ такой же, как и к любому другому статическому методу того же класса, в котором он существует.
  • Анонимный внутренний класс не виден как внешнему миру, так и другим методам или классам того же класса (вкоторый существует) и используется в той точке, гдеобъявлен

Давайте попробуем увидеть вышеизложенные концепции практически_

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

}

Надеюсь, это поможет всем.Пожалуйста, см. Больше

10 голосов
/ 18 октября 2012

Давайте разберемся со следующим простым примером.Это происходит потому, что это НЕСТАТИЧЕСКИЙ ВНУТРЕННИЙ КЛАСС.Вам нужен экземпляр внешнего класса.

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

        }
    }
}
9 голосов
/ 05 марта 2012

Thing - это внутренний класс с автоматическим подключением к экземпляру Hello. Вы получаете ошибку компиляции, потому что нет экземпляра Hello, к которому он мог бы присоединиться. Это проще всего исправить, изменив статический вложенный класс , который не имеет соединения:

static class Thing
...