如何在静态方法内实例化非静态内部类?

136

我有以下代码:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

到目前为止,代码没问题,但我无法在主方法中实例化 "in",例如 in = new Inner(),因为它显示 非静态字段不能在静态上下文中引用

有什么办法可以做到这一点吗?我不想使我的 Inner 类成为 静态的


“非静态内部”是一个自我重复的说法。 - user207421
恭喜你掌握了Java知识。标题便于搜索。 - Colm
5个回答

228

你还需要引用另一个外部类。

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

如果 Inner 是静态的,那么它将是

Inner inner = new MyClass.Inner();

61
这个回答改变了我对生活的看法。outer.new Inner()?我甚至从未考虑过这是可能的。O_O - AlbeyAmakiir
1
对于静态内部类,你难道不能简单地执行 Inner inner = new Inner() 吗? - Can Lu
1
@CanLu 创建静态嵌套类的对象时,请使用 OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass()嵌套类 - LittleLittleQ

41
一个“普通”的内部类有一个隐式指向外部类实例的指针。这使得编译器可以为你生成代码来追踪该指针,而无需你手动输入它。例如,如果在外部类中有一个变量“a”,则内部类中的代码只需执行“a = 0”,但编译器将为“outerPointer.a = 0”生成代码,在幕后维护隐藏的指针。
这意味着当您创建内部类的实例时,必须有外部类的实例与之关联。如果在外部类的方法中进行此创建,则编译器知道要使用“this”作为隐式指针。如果要链接到其他外部实例,则使用特殊的“new”语法(请参见下面的代码片段)。
如果将内部类声明为“静态”,则没有隐藏指针,您的内部类无法引用外部类的成员。静态内部类与常规类相同,但其名称作用域在父级内。
以下是一个代码片段,演示了创建静态和非静态内部类的语法:
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
Alexei Kaigorodov 的回答是正确的。他的解决方案允许您在静态方法(例如同类的 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
    }
}

补充说明:您可以从静态方法实例化静态内部类。这种代码只需要在静态方法中实例化非静态内部类时使用。 - Herbert Samuel Jennings III

-1
静态方法与类联系在一起,没有默认的 this 引用,因此需要显式地提供对象。实例方法有 this 引用,所以不需要提供对象。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接