Java-无法访问类型为Foo的封闭实例


314

我有以下代码:

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中构建工作程序有一些基本的误解。

有任何想法吗?


Answers:


483

static class Thing 将使您的程序正常运行。

实际上,您已经拥有Thing一个内部类,该内部类(根据定义)与的特定实例相关联Hello(即使它从不使用或引用它),这意味着在new Thing();不具有特定Hello实例的情况下说这是错误的范围。

如果您将其声明为静态类,则它是“嵌套”类,不需要特定的Hello实例。


这是否还意味着如果我实例化了outer classnon-static inner class即使我不在任何地方都可以使用,它也会被创建?
mr5

第一个内部类的每个对象必须有父母,但父母可以有任意数量的儿童包括0
jacobm

92

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

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

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

  • 移动Thing的出Hello类。

  • 更改Thingstatic嵌套类。

    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
    }

如果任何实例依赖有意义,则最后一个解决方案(非静态嵌套类)将是强制性的。例如,如果我们有:ThingHello

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

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

Thing t = new Thing(31);

这将是有问题的,因为enormous针对它进行测试31 并没有明显的价值。一个实例h的的Hello外部类必须提供这个h.enormous值:

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

因为如果没有,这并不意味着Thinga Hello

有关嵌套/内部类的更多信息: 嵌套类(Java教程)


您的答案是综合性的还是综合性的。即使感觉很奇怪(至少对我来说),语法也是正确的。
2014年

如果仍然有人出错,则语法Thing thing1 <<HelloInstantiation>>.new Thing()是关键。我花了几分钟混淆语法Thing thing1 new <<HelloInstantiation>>.Thing()。= P
skia.heliou,2015年

1
@ skia.heliou谢谢!我正在创建一个辅助类,并且静态变量(甚至类)不仅消除了作用域,而且它们通常效率低下。需要提供运行时参数使使用main方法变得很麻烦。这就是我所需要的,而正是我想要寻找的。
被遗弃的购物车

25

好吧...这么多好答案,但我想在上面添加更多。对Java内部类的简要介绍使我们可以在另一个类中定义一个类,并且能够以这种方式嵌套类具有某些优点:

  1. 它可以从其他类中隐藏(增加封装)该类-如果该类仅由包含在其中的类使用,则尤其相关。在这种情况下,外界无需了解它。

  2. 由于类在需要的地方按逻辑分组在一起,因此可以使代码更易于维护

  3. 内部类可以访问其包含类的实例变量和方法。

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

  1. 本地内部
  2. 静态内层
  3. 匿名内部阶层

要记住的一些重要点

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

让我们尝试实际看一下以上概念_

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

}

我希望这对每个人都有帮助。请 参考更多


建议的改进:将第一个类命名为MyOuterClass,从AnonymousClass周围删除注释。
Noumenon


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

        }
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.