Làm thế nào để khởi tạo lớp bên trong không tĩnh trong một phương thức tĩnh?


122

Tôi có đoạn mã sau:

public class MyClass {

   class Inner {
     int s, e, p;
   }

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

Cho đến phần này, mã vẫn ổn, nhưng tôi không thể khởi tạo 'in' trong phương thức chính in = new Inner()như nó đang hiển thị non static field cannot be referenced in static context.

Cách tôi có thể làm là gì? Tôi không muốn làm cho Innerlớp học của tôi tĩnh .


Câu trả lời:


201

Bạn cũng phải có một tham chiếu đến lớp bên ngoài khác.

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

Nếu Nội tại tĩnh thì nó sẽ

Inner inner = new MyClass.Inner();

53
Câu trả lời này đã thay đổi cách nhìn của tôi về cuộc sống. bên ngoài.new Nội ()? Thậm chí chưa bao giờ coi đó là một khả năng. O_O
AlbeyAmakiir

1
Đối với nội tại tĩnh, bạn không thể chỉ đơn giản làm Nội tại bên trong = new Inner ()?
Can Lu

1
@CanLu để tạo một đối tượng cho lớp lồng nhau tĩnh, sử dụng OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(). Lớp học lồng nhau
LittleLittleQ

37

Một lớp bên trong "thông thường" có một con trỏ ẩn (ngầm định) đến một cá thể lớp Bên ngoài. Điều này cho phép trình biên dịch tạo mã để đuổi theo con trỏ cho bạn mà bạn không cần phải nhập nó. Ví dụ: nếu có một biến "a" trong lớp ngoài thì mã trong lớp bên trong của bạn chỉ có thể thực hiện "a = 0", nhưng trình biên dịch sẽ tạo mã cho "externalPointer.a = 0" duy trì con trỏ ẩn bên dưới những cái ảnh bìa.

Điều này có nghĩa là khi bạn tạo một thể hiện của lớp bên trong, bạn phải có một thể hiện của lớp bên ngoài để liên kết nó với. Nếu bạn thực hiện việc tạo này bên trong một phương thức của lớp bên ngoài thì trình biên dịch sẽ biết sử dụng "this" làm con trỏ ngầm. Nếu bạn muốn liên kết với một số phiên bản bên ngoài khác thì bạn sử dụng cú pháp "mới" đặc biệt (xem đoạn mã bên dưới).

Nếu bạn đặt lớp bên trong của mình là "tĩnh" thì không có con trỏ ẩn và lớp bên trong của bạn không thể tham chiếu đến các thành viên của lớp ngoài. Một lớp bên trong tĩnh giống với một lớp thông thường, nhưng tên của nó được đặt bên trong lớp cha.

Đây là một đoạn mã trình bày cú pháp để tạo các lớp bên trong tĩnh và không tĩnh:

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

Nếu bạn muốn tạo new Inner()từ bên trong một phương thức, hãy thực hiện việc đó từ một phương thức thể hiện của lớp MyClass:

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

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

0

Alexei Kaigorodov's là câu trả lời đúng. Giải pháp của anh ấy cho phép bạn khởi tạo các lớp bên trong từ bên trong một phương thức tĩnh, chẳng hạn như một hàm main () của cùng một lớp. Nếu không, bạn không thể khởi tạo một lớp bên trong trong một phương thức tĩnh. Nó không biên dịch. Giải pháp của Alexei thực hiện biên dịch và nó cho phép bạn khởi tạo các lớp bên trong từ một phương thức tĩnh. Các câu trả lời khác là ghi chú bên lề thú vị, nhưng tôi không thấy chúng đáp ứng được câu hỏi thực tế.

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

Phụ lục: Bạn -có thể- khởi tạo các lớp bên trong tĩnh từ các phương thức tĩnh. Loại mã này chỉ cần thiết để khởi tạo các lớp bên trong không tĩnh từ bên trong các phương thức tĩnh.
Herbert Samuel Jennings III
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.