Java - нет включающего экземпляра типа Foo


314

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

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.

Любые идеи?


Ответы:


483

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

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

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


Означает ли это также, что, если я создам экземпляр outer class, non-static inner classбудет создан объект, даже если я его нигде не использую?
mr5

Нет. У каждого объекта внутреннего класса должен быть родитель, но у родителя может быть любое количество детей, включая 0.
jacobm

92

Вы объявили класс 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)


Ваш ответ является всеобъемлющим и синтетическим. Даже если это кажется странным (по крайней мере для меня), синтаксис правильный.
boumbh

Если кто-то все еще получает ошибки, синтаксис Thing thing1 <<HelloInstantiation>>.new Thing()является ключевым. Я провел несколько минут в замешательстве, используя синтаксис Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou

1
@ skia.heliou Спасибо! Я делал вспомогательный класс, и статические переменные (или даже классы) не только исключают область видимости, но и часто неэффективны. Необходимость предоставления аргументов времени выполнения затрудняет использование основного метода. Это было все, что мне было нужно, и именно то, что я искал, чтобы найти.
Заброшенная корзина

25

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

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

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

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

У нас есть в основном три типа Inner Classes

  1. Местный внутренний
  2. Статический внутренний класс
  3. Аноним Внутренний Класс

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

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

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

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

}

Я надеюсь, что это поможет всем. Пожалуйста, обратитесь к более


Предлагаемые улучшения: назовите первый класс MyOuterClass, удалите комментарии вокруг AnonymousClass.
Нумен

9

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

static class Thing

9

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

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

        }
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.