Java - 不能访问类型为Foo的封闭实例

问题描述 投票:287回答:5

我有以下代码:

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!");
    }
}

我知道Thing什么都不做,但我的Hello,World程序在没有它的情况下编译得很好。这只是我定义的类失败了。

它拒绝编译。我得到No enclosing instance of type Hello is accessible."在创造新事物的线上。我猜是:

  1. 我有系统级问题(在DrJava或我的Java安装中)或
  2. 我对如何在java中构建一个工作程序有一些基本的误解。

有任何想法吗?

java inner-classes
5个回答
454
投票

static class Thing将使您的计划有效。

事实上,你有Thing作为一个内部类,它(根据定义)与Hello的特定实例相关联(即使它从未使用或引用它),这意味着如果没有一个new Thing();,这是一个错误特别是Hello范围内的实例。

如果你将它声明为静态类,那么它就是一个“嵌套”类,它不需要特定的Hello实例。


87
投票

您已将类Thing声明为非静态内部类。这意味着它必须与Hello类的实例相关联。

在您的代码中,您尝试从静态上下文创建Thing的实例。这就是编译器所抱怨的。

有一些可能的解决方案。使用哪种解决方案取决于您想要实现的目标。

  • Thing移出Hello类。
  • Thing更改为static嵌套类。 static class Thing
  • 在创建Hello实例之前创建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 }

如果Thing的任何实例依赖于Hello的实例是有意义的,那么最后一个解决方案(非静态嵌套类)将是必需的。例如,如果我们有:

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

任何创建类Thing对象的原始尝试,如:

Thing t = new Thing(31);

会有问题,因为没有明显的enormous值来测试31对它。 h外部类的实例Hello是提供此h.enormous值所必需的:

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

因为它不意味着Thing,如果它没有Hello

有关嵌套/内部类的更多信息:Nested Classes (The Java Tutorials)


24
投票

嗯...这么多好的答案,但我想在它上面添加更多。简要介绍Java-Java中的Inner类允许我们在另一个类中定义一个类,并且能够以这种方式嵌套类具有以下优点:

  1. 它可以隐藏(它增加封装)来自其他类的类 - 特别是如果该类仅被包含在其中的类使用的话。在这种情况下,外界不需要了解它。
  2. 它可以使代码更易于维护,因为类在逻辑上按需要分组。
  3. 内部类可以访问其包含类的实例变量和方法。

我们主要有三种类型的Inner Classes

  1. 本地内心
  2. 静态内在类
  3. 匿名内在阶级

一些重要的要点需要记住

  • 我们需要类对象来访问它所在的Local Inner Class。
  • 静态内部类直接访问,就像存在它的同一个类的任何其他静态方法一样。
  • 匿名内部类对于外部世界以及同一类的其他方法或类(在其中存在)是不可见的,并且它在声明它的位置使用。

让我们试着看看上面的概念_

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!");
    }
 }

}

我希望这对每个人都有帮助。请refer for more


9
投票

Thing是一个inner class,与Hello的实例自动连接。您收到编译错误,因为没有Hello实例可以附加到它。您可以通过将其更改为没有连接的static nested class来最轻松地修复它:

static class Thing

9
投票

让我们用以下简单的例子来理解它。这是因为这是非静态内部类。你应该需要外类的实例。

 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");

        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.