Як інсталювати нестатичний внутрішній клас у статичному методі?


122

У мене є такий код:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

До цієї частини код добре, але я не в змозі інстанціювати "в" в основному методі, як in = new Inner()показано non static field cannot be referenced in static context.

Який спосіб я можу це зробити? Я не хочу робити свій Innerклас статичним .


Відповіді:


201

Ви також повинні мати посилання на інший зовнішній клас.

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

Якби Внутрішня була статичною, то це було б

Inner inner = new MyClass.Inner();

53
Ця відповідь просто змінила мій погляд на життя. external.new Внутрішня ()? Ніколи навіть не вважав це можливим. О_О
AlbeyAmakiir

1
Для статичного внутрішнього, ви не можете просто зробити Inner Internal = new Inner ()?
Може Лу

1
@CanLu для створення об'єкта для статичного вкладеного класу, використовуйте OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Вкладені класи
LittleLittleQ

37

"Нормальний" внутрішній клас має прихований (неявний) вказівник на екземпляр Зовнішнього класу. Це дозволяє компілятору генерувати код, щоб переслідувати вказівник за вами, не потребуючи введення його. Наприклад, якщо в зовнішньому класі є змінна "a", то код у вашому внутрішньому класі може просто робити "a = 0", але компілятор генерує код для "externalPointer.a = 0", підтримуючи прихований покажчик під обкладинки.

Це означає, що коли ви створюєте екземпляр внутрішнього класу, ви повинні мати екземпляр зовнішнього класу, щоб пов’язати його. Якщо ви робите це створення всередині методу зовнішнього класу, тоді компілятор знає використовувати "це" як неявний покажчик. Якщо ви хочете встановити посилання на якийсь інший зовнішній екземпляр, тоді ви використовуєте спеціальний "новий" синтаксис (див. Фрагмент коду нижче).

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

Ось фрагмент коду, який демонструє синтаксис для створення статичних та нестатичних внутрішніх класів:

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

    }

}

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