是啥导致错误“无法访问 Foo 类型的封闭实例”,我该如何解决?

Posted

技术标签:

【中文标题】是啥导致错误“无法访问 Foo 类型的封闭实例”,我该如何解决?【英文标题】:What causes error "No enclosing instance of type Foo is accessible" and how do I fix it?是什么导致错误“无法访问 Foo 类型的封闭实例”,我该如何解决? 【发布时间】:2012-03-22 13:37:48 【问题描述】:

我有以下代码:

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."。我猜是:

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

有什么想法吗?

【问题讨论】:

Java inner class and static nested class 的可能重复项 【参考方案1】:

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

static class Thing

【讨论】:

【参考方案2】:

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

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

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

【讨论】:

这是否也意味着如果我实例化outer class,即使我没有在任何地方使用它也会创建non-static inner class 没有。内部类的每个对象都必须有父对象,但父对象可以有任意数量的子对象,包括 0。【参考方案3】:

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

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

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

Thing 移出Hello 类。

Thing 更改为static 嵌套类。

static class Thing

在创建Thing 的实例之前创建Hello一个实例

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 。 Hello 外部类的实例 h 是提供此 h.enormous 值所必需的:

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

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

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

【讨论】:

您的回答既全面又综合。即使感觉很奇怪(至少对我来说),语法是正确的。 如果还有人遇到错误,语法Thing thing1 <<HelloInstantiation>>.new Thing() 是关键。我花了几分钟混淆使用语法Thing thing1 new <<HelloInstantiation>>.Thing()。 =P @skia.heliou 谢谢!我正在制作一个辅助类和静态变量(甚至类),不仅消除了作用域,而且它们通常效率低下。需要提供运行时参数使得使用 main 方法很麻烦。这就是我所需要的,正是我想要找到的。【参考方案4】:

让我们通过下面的简单示例来理解它。 发生这种情况是因为这是非静态内部类。你应该需要外部类的实例。

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

        
    

【讨论】:

【参考方案5】:

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

    它可以隐藏(它增加封装)其他类的类 - 如果该类仅由它包含的类使用,则尤其相关。在这种情况下,外界就不需要知道了。

    它可以使代码更易于维护,因为这些类在需要它们的地方按逻辑分组在一起。

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

我们主要有三种Inner Classes

    局部内 静态内部类 匿名内部类

需要记住的一些要点

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

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

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

【讨论】:

建议改进:将第一个类命名为 MyOuterClass,从 AnonymousClass 周围删除 cmets。【参考方案6】:

INNER 类 Thing 声明为 static,它可以正常工作。

我记得当我将内部类 Dog 声明为 class Dog 时,我遇到了同样的问题。我遇到了和你一样的问题。 有两种解决方案

1- 将内部类 Dog 声明为静态。 或者

2- 将内部类 Dog 自己移动到一个新类中。

示例如下:

公共类 ReturnDemo

public static void main(String[] args) 
    
    int z = ReturnDemo.calculate(10, 12);
    System.out.println("z = " + z);
    
    ReturnDemo.Dog dog = new Dog("Bosh", " Doggy");
    System.out.println( dog.getDog());



public static int calculate (int x, int y) 
    return x + y;


public void print( ) 
    System.out.println("void method");
    return;


public String getString() 
    return "Retrun String type value";



static class Dog 
    
private String breed;
private String name;

public Dog(String breed, String name) 
    super();
    this.breed = breed;
    this.name = name;


public Dog getDog() 
    // return Dog type;
    return this;
    


public String toString() 
    return "breed" + breed.concat("name: " + name);


【讨论】:

【参考方案7】:

Java 14 之前 您必须添加 static 关键字才能从静态上下文访问类 Thing

class Hello 
    static class Thing 
        public int size;

        Thing() 
            size = 0;
        
    

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

Java 14+ 从 Java 14 开始,您可以使用内部记录类,它们是隐式静态的。所以你会:

class Hello 
    record Thing(int size)  

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

【讨论】:

请注意,size 在使用记录时将是 final【参考方案8】:

我的朋友试试这个:(你也可以叫它 Hello 而不是 Main)

class Thing 
  public int size;

    Thing() 
      size = 0;
    



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

这背后的想法是您必须创建一个单独的类来包含静态 void main (String[] args) 方法。总结:您必须有一个将创建您的对象的类,以及另一个包含对象创建的类(在前一个之外)。如果你称它为 Main,你应该有一个名为 Main.java 的文件。如果你想叫它Hello,那么你的文件必须命名为Hello.java

【讨论】:

以上是关于是啥导致错误“无法访问 Foo 类型的封闭实例”,我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

是啥导致 cellForRowAtIndexPath 中的 outOfBounds 错误?

是啥导致发生分段错误?

是啥导致 HttpListener HTTP 503 错误?

Python MySQLdb错误 - 是啥导致了这个

NullPointerException,是啥导致我的错误?

是啥导致了这个“jpackage 不存在”错误?