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

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

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.

Ответ 1

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

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

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

Inner inner = new MyClass.Inner();

Ответ 2

"Обычный" внутренний класс имеет скрытый (неявный) указатель на экземпляр класса Outer. Это позволяет компилятору генерировать код, чтобы преследовать указатель для вас, не набирая его. Например, если во внешнем классе есть переменная "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

    }

}

Ответ 3

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

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

public static void main(String args[]){
  new MyClass().main();
}

Ответ 4

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

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