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)


Ваша відповідь є вичерпною та синтетичною. Навіть якщо це дивно (мені щонайменше), синтаксис правильний.
бумб

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

1
@ skia.heliou Дякую! Я робив клас помічників і статичні змінні (або навіть класи) не тільки усувають область застосування, але вони часто неефективні. Необхідність наводити аргументи часу виконання неприємностей використовувати основний метод. Це було все, що мені було потрібно, і саме те, що я шукав.
Покинутий кошик

25

Ну ... так багато хороших відповідей, але я хочу додати більше. Короткий огляд класу «Внутрішній» на 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.