ChatGPT解决这个技术问题 Extra ChatGPT

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

我有以下代码:

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

有任何想法吗?


j
jacobm

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

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

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


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

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

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

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

将 Thing 移出 Hello 类。

将 Thing 更改为静态嵌套类。静态类事物

在创建 Thing 实例之前创建 Hello 实例。 public static void main(String[] args) { Hello h = new Hello();事物事物 1 = h.new事物(); // 希望这个语法是正确的,即时输入 :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 方法很麻烦。这就是我所需要的,正是我想要找到的。
R
Rupesh Yadav

嗯......这么多好的答案,但我想添加更多。 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 周围的注释。
如前所述,reanonymousClass 语句无效,因为分配将失败。
C
Community

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

static class Thing

A
AZ_

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

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

        }
    }
}

Ł
Łukasz Rzeszotarski

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
M
Maged Almaweri

将 INNER 类 Thing 声明为静态,它将毫无问题地工作。

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

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

}


J
Johann

试试这个,我的朋友:(你也可以叫它 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


M
Mark
class Hello {
    class Thing {
        public int size;

        Thing() {
            size = 0;
        }
    }

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

您的答案可以通过额外的支持信息得到改进。请edit添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以找到有关如何写出好答案的更多信息in the help center
R
Rabhi salim

就我而言,这是因为多了一个“}”