Как создать экземпляр нестатического внутреннего класса в статическом методе?

122

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

public class MyClass {

   class Inner {
     int s, e, p;
   }

   public static void main(String args[]) {
     Inner in;
   }
}

До этой части код в порядке, но я не могу создать экземпляр «in» в основном методе, in = new Inner()как показано на рисунке non static field cannot be referenced in static context.

Как я могу это сделать? Я не хочу делать свой Innerкласс статичным .

Виктор Мукерджи
источник

Ответы:

201

У вас также должна быть ссылка на другой внешний класс.

Inner inner = new MyClass().new Inner();

Если бы Inner был статическим, то это было бы

Inner inner = new MyClass.Inner();
RNJ
источник
53
Этот ответ просто изменил мои взгляды на жизнь. external.new Inner ()? Никогда даже не считал это возможным. O_O
AlbeyAmakiir 07
1
Для статического внутреннего, не могли бы вы просто сделать Inner inner = new Inner ()?
Can Lu
1
@CanLu для создания объекта для статического вложенного класса используйте OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Вложенные классы
LittleLittleQ
37

«Обычный» внутренний класс имеет скрытый (неявный) указатель на экземпляр внешнего класса. Это позволяет компилятору сгенерировать код для отслеживания указателя без необходимости его ввода. Например, если есть переменная «a» во внешнем классе, тогда код во внутреннем классе может просто выполнять «a = 0», но компилятор сгенерирует код для «outerPointer.a = 0», сохраняя скрытый указатель под обложки.

Это означает, что когда вы создаете экземпляр внутреннего класса, у вас должен быть экземпляр внешнего класса, чтобы связать его. Если вы делаете это создание внутри метода внешнего класса, компилятор знает, что нужно использовать this в качестве неявного указателя. Если вы хотите установить ссылку на какой-либо другой внешний экземпляр, используйте специальный «новый» синтаксис (см. Фрагмент кода ниже).

Если вы сделаете свой внутренний класс «статическим», тогда не будет скрытого указателя, и ваш внутренний класс не сможет ссылаться на члены внешнего класса. Статический внутренний класс идентичен обычному классу, но его имя находится внутри родительского класса.

Вот фрагмент кода, демонстрирующий синтаксис для создания статических и нестатических внутренних классов:

public class MyClass {

    int a,b,c; // Some members for MyClass

    static class InnerOne {
        int s,e,p;
        void clearA() {
            //a = 0;  Can't do this ... no outer pointer
        }
    }

    class InnerTwo {
        //MyClass parentPointer;      Hidden pointer to outer instance
        void clearA() {         
            a = 0;
            //outerPointer.a = 0      The compiler generates this code
        }       
    }

    void myClassMember() {
        // The compiler knows that "this" is the outer reference to give
        // to the new "two" instance.
        InnerTwo two = new InnerTwo(); //same as this.new InnerTwo()
    }

    public static void main(String args[]) {

        MyClass outer = new MyClass();

        InnerTwo x = outer.new InnerTwo(); // Have to set the hidden pointer
        InnerOne y = new InnerOne(); // a "static" inner has no hidden pointer
        InnerOne z = new MyClass.InnerOne(); // In other classes you have to spell out the scope

    }

}
ChrisCantrell
источник
4

Если вы хотите создать new Inner()из метода, сделайте это из метода экземпляра класса MyClass:

public void main(){
  Inner inner = new Inner();
}

public static void main(String args[]){
  new MyClass().main();
}
Алексей Кайгородов
источник
0

Алексей Кайгородов - правильный ответ. Его решение позволяет создавать экземпляры внутренних классов из статического метода, такого как main () того же класса. В противном случае вы не сможете создать экземпляр внутреннего класса в статическом методе. Не компилируется. Решение Алексея компилируется и позволяет создавать экземпляры внутренних классов из статического метода. Другие ответы представляют собой интересные примечания, но я не считаю их ответами на конкретный вопрос.

import java.awt.Graphics;
import java.awt.Color;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class Example {
    public class InnerClass extends JPanel {
        public void paint(Graphics g) {
            g.setColor(Color.BLACK);
            g.fillRect(getX(),getY(),getWidth(),getHeight());
            g.setColor(Color.RED);
            g.fillRect(5, 20, 195, 20);
            g.setColor(Color.BLACK);
            g.drawString("This was written by an inner class.", 10, 35);
        }
    }

    public void demonstrate() {
        InnerClass sc = new InnerClass();//<---this is key
        JFrame jf = new JFrame();
        jf.add(sc);
        jf.setSize(220, 130);
        jf.setLocation(450, 450);
        jf.show();
    }

    public static void main(String[] params) {
        Example e = new Example();//<---so is this
        e.demonstrate();//<---and this is also key
    }
}
Герберт Сэмюэл Дженнингс III
источник
Приложение: Вы можете создавать статические внутренние классы из статических методов. Такой код необходим только для создания нестатических внутренних классов из статических методов.
Герберт Сэмюэл Дженнингс III,