Не є класом Java, що додається


366

Я намагаюся зробити гру Tetris, і я отримую помилку компілятора

Shape is not an enclosing class

коли я намагаюся створити об’єкт

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Я використовую внутрішні класи для кожної форми. Ось частина мого коду

public class Shapes {
    class AShape {
    }
    class ZShape {
    }
}

Що я роблю неправильно?


160
new Shape().new ZShape();. Класу ZShapeпотрібний екземпляр, що додається, для екземпляра.
Сотіріос Деліманоліс

4
перемістити внутрішній клас до окремого файлу
Dimmduh

@Dimmduh коментар повинен бути відповіддю в цьому випадку. Вони не повинні бути внутрішніми класами. Переміщення їх визначило б інші проблеми з класом Shape, які існують.
Єремія Адамс

Тут не відповідати на питання, але чи можу я запропонувати використовувати спадщину тут AShapeі де ZShapeрозширити базовий клас Shapes. Класи вкладання - це не дуже хороший дизайн для цієї проблеми.
Paramvir Singh Karwal

Відповіді:


492

ZShape не є статичним, тому для нього потрібен екземпляр зовнішнього класу.

Найпростіше рішення - зробити ZShape і будь-який вкладений клас, staticякщо можете.

Я б також зробив будь-які поля finalчи static finalщо ви також можете.


13
Створення ZShape staticцілком перемагає мету того, що він намагається зробити, а це - копія копії ZShape.
Cardano

17
@Cardano staticробить це легше, а не важче.
Пітер Лоурі

12
ще одне простого рішення , щоб зробити вміщає клас Instantiate внутрішнього класу, тобто отримувати ZShape таким чином: ZShape myShape = new Shape().instantiateZShape();. Це означає, що отриманий ZShape не існує без форми, що є тут наміром.
Вінс

@ Peter Lawrey Як ти зрозумів, що всі екземпляри Shape повинні використовувати один і той же ZShape? Я не отримую цього від його джерела.
Неймовірний січень

2
Є 2 випадки, якщо ми хочемо статичний або екземпляр. Зробити його статичним не завжди допоможе.
Йогеш Чуахан

177

Припустимо, RetailerProfileModel - ваш основний клас, а RetailerPaymentModel - це внутрішній клас всередині нього. Ви можете створити об'єкт класу Внутрішній поза класом наступним чином:

RetailerProfileModel.RetailerPaymentModel paymentModel
        = new RetailerProfileModel().new RetailerPaymentModel();

34
Ця відповідь була дуже корисною, я ніколи не знав, що ти можеш дзвонити новим двічі поспіль (а я робив Java протягом 8+ років!)
PaulBGD

1
Ви, безумовно, можете зателефонувати новому оператору будь-яку кількість разів, поки не захочете зберігати посилання на цей об’єкт.
Вішал Кумар

1
Якщо об’єкт внутрішнього класу створений таким чином, як він отримує доступ до членів зовнішнього класу?
Сінган Хуан

1
У самому внутрішньому класі ви можете використовувати OuterClass.this.Я не думаю, що існує спосіб отримати екземпляр поза кодом внутрішнього класу. Звичайно, ви завжди можете представити власну власність: public OuterClass getOuter () {return OuterClass.this; }
Вішал Кумар

Працює для тестів:underTest = Mockito.mock(Outer.class).new InnerNonStaticClass();
фельдхаге

48

Я б сказав, що це не перетворення нестатичного класу в статичний клас, оскільки в цьому випадку ваш внутрішній клас не може отримати доступ до нестатичних членів зовнішнього класу.

Приклад:

class Outer
{
    class Inner
    {
        //...
    }
}

Тож у такому випадку ви можете зробити щось на кшталт:

Outer o = new Outer();
Outer.Inner obj = o.new Inner();

Як щодо Outer.Inner obj = (новий Зовнішній) .new Inner ();
Hussain KMR Behestee

1
@HussainKMRBehestee, ні, це не працювало б точно. Однак це спрацювало бOuter.Inner obj = new Outer().new Inner();
Аміт Упадгай

Але Аміт, це працює на мене. Я був би радий, якщо ви можете пояснити, чому це не повинно працювати.
Хусейн KMR Behestee

1
@HussainKMRBehestee, пояснення: Я можу лише здогадуватися, що граматика на Java говорить про те, що для інстанціювання класу нам потрібно викликати конструктор, а при виклику конструктора ()обов'язковий. Однак C, C ++ це не обов'язково. Ось приклад, який не працює. Більше того, я знайшов цю посаду . що пояснює більше про граматику на Java та те, як вони розбираються. Я хотів би побачити зразок випадку, коли цей синтаксис працює для вас.
Аміт Упадхей

1
О, моє погано, це був помилковий помилок, Outer.Inner obj = (new Outer ()). New Inner (); сподіваюся, що цього разу це нормально і дякую, що помітили це.
Hussain KMR Behestee

18

Як зазначено в документах :

OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Мухаммад Омер Аслам

Дякую! Тільки починаємо.
Бренан Міллер

10

Іноді нам потрібно створити новий екземпляр внутрішнього класу, який не може бути статичним, оскільки це залежить від деяких глобальних змінних батьківського класу. У цій ситуації, якщо ви спробуєте створити екземпляр внутрішнього класу, який не є статичним, not an enclosing classвикидається помилка.

Беручи приклад питання, що робити, якщо ZShapeне може бути статичним, оскільки йому потрібна глобальна змінна Shapeкласу?

Як можна створити новий екземпляр ZShape? Ось як:

Додайте геттер у батьківський клас:

public ZShape getNewZShape() {
    return new ZShape();
}

Отримайте доступ до нього так:

Shape ss = new Shape();
ZShape s = ss.getNewZShape();


1

Я зіткнувся з тією ж проблемою. Я вирішив, створивши екземпляр для кожного внутрішнього загальнодоступного класу. що стосується вашої ситуації, я пропоную вам використовувати спадщину, крім внутрішніх класів.

public class Shape {

    private String shape;

    public ZShape zShpae;
    public SShape sShape;

    public Shape(){
      int[][] coords =  noShapeCoords;
      shape = "NoShape";
      zShape = new ZShape();
      sShape = new SShape();
    }

    class ZShape{
      int[][] coords =  zShapeCoords;
      String shape = "ZShape";
    }

    class SShape{
      int[][] coords = sShapeCoords;
      String shape = "SShape";
    }

 //etc
}

тоді ви можете новий Shape (); і відвідати ZShape через shape.zShape;


1
Неправильне рішення. Логічна помилка. Якщо внутрішній клас (наприклад, ZShape) вимагає встановлення будь-якого поля, у конструкторі зовнішнього класу ви повинні його отримати! public Shape (String field1_innerClass, int field2_innerClass ...) {zShape = new ZShape (String field1_innerClass, int field2_innerClass ...) ...}}
Mohsen Abasi

1

Не потрібно робити вкладений клас статичним, але він повинен бути відкритим

public class Test {
    public static void main(String[] args) {
        Shape shape = new Shape();
        Shape s = shape.new Shape.ZShape();
    }
}

1

Одне, що я спочатку не зрозумів, читаючи прийняту відповідь, - це те, що стати внутрішнім класом статичним - це в основному те саме, що перемістити його в свій окремий клас.

Таким чином, при отриманні помилки

xxx не є класом, що охоплює

Вирішити це можна будь-яким із наступних способів:

  • Додайте staticключове слово до внутрішнього класу, або
  • Перенесіть його в свій окремий клас.

1

У випадку, якщо батьківський клас є однотонним, використовуйте наступний спосіб:

Parent.Child childObject = (Parent.getInstance()).new Child();

куди getInstance()повернеться батьківський об'єкт одиночного класу.


0

Щоб досягти вимоги з питання, ми можемо розмістити класи в інтерфейсі:

public interface Shapes {
    class AShape{
    }
    class ZShape{
    }
}

а потім використовувати як автор, який пробував раніше:

public class Test {
    public static void main(String[] args) {
        Shape s = new Shapes.ZShape();
    }
}

Якщо ми шукаємо правильне "логічне" рішення, слід використовувати fabricмодель дизайну

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.