Java - Không thể truy cập thể hiện kèm theo của loại Foo


314

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

class Hello {
    class Thing {
        public int size;

        Thing() {
            size = 0;
        }
    }

    public static void main(String[] args) {
        Thing thing1 = new Thing();
        System.out.println("Hello, World!");
    }
}

Tôi biết Thingkhông làm gì, nhưng chương trình Hello, World của tôi chỉ biên dịch tốt nếu không có nó. Chỉ có các lớp được xác định là thất bại đối với tôi.

Và nó từ chối biên dịch. Tôi nhận được No enclosing instance of type Hello is accessible."ở dòng tạo ra một điều mới. Tôi cũng đoán vậy:

  1. Tôi gặp vấn đề ở cấp hệ thống (trong cài đặt DrJava hoặc Java) hoặc
  2. Tôi có một số hiểu lầm cơ bản về cách xây dựng một chương trình làm việc trong java.

Có ý kiến ​​gì không?


Câu trả lời:


483

static class Thing sẽ làm cho chương trình của bạn hoạt động.

Như vậy, bạn đã có Thingmột lớp bên trong, (theo định nghĩa) được liên kết với một thể hiện cụ thể của Hello(ngay cả khi nó không bao giờ sử dụng hoặc đề cập đến nó), điều đó có nghĩa là đó là một lỗi để nói new Thing();mà không có một Hellotrường hợp cụ thể trong phạm vi.

Nếu bạn khai báo nó là một lớp tĩnh thay vào đó, thì đó là một lớp "lồng nhau", không cần một thể hiện cụ Hellothể.


Điều này cũng có nghĩa là nếu tôi khởi tạo outer class, non-static inner classnó cũng sẽ được tạo ngay cả khi tôi không sử dụng nó ở bất cứ đâu?
mr5

Không. Mọi đối tượng của một lớp bên trong phải có cha mẹ, nhưng cha mẹ có thể có bất kỳ số lượng con nào trong đó có 0.
jacobm

92

Bạn đã khai báo lớp Thinglà một lớp bên trong không tĩnh. Điều đó có nghĩa là nó phải được liên kết với một thể hiện của Hellolớp.

Trong mã của bạn, bạn đang cố gắng tạo một phiên bản Thingtừ bối cảnh tĩnh. Đó là những gì trình biên dịch đang phàn nàn về.

Có một vài giải pháp có thể. Giải pháp nào để sử dụng phụ thuộc vào những gì bạn muốn đạt được.

  • Di chuyển Thingra khỏi Hellolớp.

  • Thay đổi Thingthành một staticlớp lồng nhau.

    static class Thing
  • Tạo một thể hiện Hellotrước khi tạo một thể hiện của Thing.

    public static void main(String[] args)
    {
        Hello h = new Hello();
        Thing thing1 = h.new Thing(); // hope this syntax is right, typing on the fly :P
    }
    

Giải pháp cuối cùng (một lớp lồng không tĩnh ) sẽ là bắt buộc nếu bất kỳ trường hợp nào Thingphụ thuộc vào một thể Hellohiện có ý nghĩa. Ví dụ: nếu chúng ta có:

public class Hello {
    public int enormous;

    public Hello(int n) {
        enormous = n;
    }

    public class Thing {
        public int size;

        public Thing(int m) {
            if (m > enormous)
                size = enormous;
            else
                size = m;
        }
    }
    ...
}

bất kỳ nỗ lực thô nào để tạo một đối tượng của lớp Thing, như trong:

Thing t = new Thing(31);

sẽ có vấn đề, vì sẽ không có enormousgiá trị rõ ràng để kiểm tra 31 chống lại nó. Một thể hiện hcủa Hellolớp bên ngoài là cần thiết để cung cấp h.enormousgiá trị này :

...
Hello h = new Hello(30);
...
Thing t = h.new Thing(31);
...

Bởi vì nó không có nghĩa là Thingnếu nó không có a Hello.

Để biết thêm thông tin về các lớp lồng nhau / bên trong: Các lớp lồng nhau (Các hướng dẫn Java)


Câu trả lời của bạn là toàn diện và tổng hợp. Ngay cả khi nó cảm thấy lạ (ít nhất là với tôi), cú pháp là chính xác.
boumbh

Nếu bất cứ ai vẫn nhận được lỗi, cú pháp Thing thing1 <<HelloInstantiation>>.new Thing()là chìa khóa. Tôi đã dành một vài phút bối rối bằng cách sử dụng cú pháp Thing thing1 new <<HelloInstantiation>>.Thing(). = P
skia.heliou

1
@ skia.heliou Cảm ơn! Tôi đã tạo ra một lớp trợ giúp và các biến tĩnh (hoặc thậm chí các lớp) không chỉ loại bỏ phạm vi, mà chúng thường không hiệu quả. Cần cung cấp các đối số thời gian chạy làm cho nó bận tâm để sử dụng một phương thức chính. Đây là tất cả những gì tôi cần và chính xác những gì tôi đang tìm kiếm.
Giỏ hàng bị bỏ rơi

25

Chà ... rất nhiều câu trả lời hay nhưng tôi muốn thêm nhiều hơn vào nó. Một cái nhìn ngắn gọn về lớp bên trong trong Java- Java cho phép chúng ta định nghĩa một lớp trong một lớp khác và việc có thể lồng các lớp theo cách này có những lợi thế nhất định:

  1. Nó có thể ẩn (Nó tăng đóng gói) lớp khỏi các lớp khác - đặc biệt có liên quan nếu lớp chỉ được sử dụng bởi lớp mà nó được chứa trong đó. Trong trường hợp này, không cần cho thế giới bên ngoài biết về nó.

  2. Nó có thể làm cho mã dễ bảo trì hơn vì các lớp được nhóm hợp lý với nhau xung quanh nơi cần thiết.

  3. Lớp bên trong có quyền truy cập vào các biến thể hiện và các phương thức của lớp chứa nó.

Chúng tôi chủ yếu có ba loại Inner Classes

  1. Nội địa
  2. Lớp bên trong tĩnh
  3. Lớp bên trong vô danh

Một số điểm quan trọng cần nhớ

  • Chúng ta cần đối tượng lớp để truy cập Lớp bên trong cục bộ mà nó tồn tại.
  • Lớp bên trong tĩnh được truy cập trực tiếp giống như bất kỳ phương thức tĩnh nào khác của cùng một lớp mà nó tồn tại.
  • Lớp bên trong ẩn danh không thể nhìn thấy bên ngoài thế giới cũng như các phương thức hoặc lớp khác cùng loại (trong đó nó tồn tại) và nó được sử dụng tại điểm mà nó được khai báo.

Hãy thử xem các khái niệm trên thực tế_

public class MyInnerClass {

public static void main(String args[]) throws InterruptedException {
    // direct access to inner class method
    new MyInnerClass.StaticInnerClass().staticInnerClassMethod();

    // static inner class reference object
    StaticInnerClass staticInnerclass = new StaticInnerClass();
    staticInnerclass.staticInnerClassMethod();

    // access local inner class
    LocalInnerClass localInnerClass = new MyInnerClass().new LocalInnerClass();
    localInnerClass.localInnerClassMethod();

    /*
     * Pay attention to the opening curly braces and the fact that there's a
     * semicolon at the very end, once the anonymous class is created:
     */
    /*
     AnonymousClass anonymousClass = new AnonymousClass() {
         // your code goes here...

     };*/
 }

// static inner class
static class StaticInnerClass {
    public void staticInnerClassMethod() {
        System.out.println("Hay... from Static Inner class!");
    }
}

// local inner class
class LocalInnerClass {
    public void localInnerClassMethod() {
        System.out.println("Hay... from local Inner class!");
    }
 }

}

Tôi hy vọng điều này sẽ giúp cho tất cả mọi người. Vui lòng tham khảo thêm


Các cải tiến được đề xuất: đặt tên cho lớp MyOuterClass đầu tiên, xóa các nhận xét từ xung quanh AnonymousClass.
Noumenon

9

Thinglà một lớp bên trong với một kết nối tự động đến một thể hiện của Hello. Bạn nhận được một lỗi biên dịch vì không có trường hợp Hellonào để đính kèm. Bạn có thể sửa nó dễ dàng nhất bằng cách thay đổi nó thành một lớp lồng tĩnh không có kết nối:

static class Thing

9

Hãy hiểu nó với ví dụ đơn giản sau đây. Điều này xảy ra bởi vì đây là LỚP HỌC KHÔNG TUYỆT VỜI. Bạn nên cần ví dụ của lớp bên ngoài.

 public class PQ {

    public static void main(String[] args) {

        // create dog object here
        Dog dog = new PQ().new Dog();
        //OR
        PQ pq = new PQ();
        Dog dog1 = pq.new Dog();
    }

    abstract class Animal {
        abstract void checkup();
    }

    class Dog extends Animal {
        @Override
        void checkup() {
            System.out.println("Dog checkup");

        }
    }

    class Cat extends Animal {
        @Override
        void checkup() {
            System.out.println("Cat Checkup");

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