【问题标题】:Why can't create instance of local class in Java?为什么不能在 Java 中创建本地类的实例?
【发布时间】:2014-03-14 19:11:54
【问题描述】:

如果我有这个代码。

public class Test{
        {
            class People {

            }
        }

        public static void main(String[] args) {
            People person = new People();//Compile ERROR
        }

    }

我无法创建 People 实例。

这是否意味着 Initializer Block 不能用于定义类?

【问题讨论】:

  • 如果您发布您遇到的确切错误,这对每个人都会更好。
  • 您正在做的是创建local class,它通常只能在您声明的范围内使用。要在此范围之外使用它,您可能必须使用反射。

标签: java class field local-class


【解决方案1】:

(添加第二个答案,因为我的错误一个已经获得了三个赞成票。)

可以在初始化程序块中声明一个类 - 但它的范围是该初始化程序块,就像您在方法中声明它一样。所以这行得通:

public class Test {
    {
        class People {            
        }

        People people = new People();
        System.out.println("In initializer block!");
    }

    public static void main(String[] args) {
        new Test();
    }
}

虽然我不能说我以前做过这件事,我也无法想象自己想在短期内做这件事。请注意,这是一个local class,它始终隐含地是一个内部类。 (虽然如果你在静态方法中声明一个本地类,没有封闭的实例,只是为了让术语有点奇怪......)

如果您想创建一个在初始化程序块之外的代码可以“看到”的类,您需要在初始化程序块之外声明它。 (就像任何其他声明一样 - 如果您在初始化程序块中声明了一个变量,您不会期望能够在外面看到它吗?)

【讨论】:

  • 附带说明,该类声明不能是 static,正如您之前建议的和其他答案所建议的那样。
  • @m0skit0:确实,因为它是本地类。 (当然,因此删除了我的答案 - 我犯了其他人都犯的同样错误,但我不希望我的第二次尝试以 +3 票优势开始:)
【解决方案2】:

你需要使内部类static:

static class People {

【讨论】:

  • 这里还有一个问题,我认为这个答案没有解决:内部类声明周围有一组额外的 {}。简单地将其设为静态不会使其编译。
  • 这也是我的第一个答案,但这不是问题的真正意义。
  • 这也不行:“本地类 People 的非法修饰符;只允许抽象或最终”
  • @JonSkeet 我本来想对你的问题发表评论,但你删除得太快了!
【解决方案3】:

初始化程序块(由额外的括号定义)改变了声明类的范围,因此它不会在外部可见,就像变量不可见一样。因此,可以创建 People 对象的唯一位置是在块本身内,例如

{
   class People {
   }

   People person = new People();
}

如果没有初始化程序块,您可以遵循 2 个选项:

  1. People 类声明为静态
  2. 创建一个 Test 对象,然后实例化一个 People 对象

在第一种情况下,唯一改变的是行

static class People

对于第二种情况,main 方法看起来像

public static void main(String[] args) {
    People person = new Test().new People();
}

【讨论】:

  • 额外的括号意味着存在 - 请阅读问题的最后一句话。
【解决方案4】:

你可以的

Test t = new Test();
People person = t. new People();

因为 People 没有封闭实例

编辑:

由于类定义在初始化块中,它只能在本地可见和可用,在初始化块内部(这使得它成为定义类的特殊位置)。 People 类在 main 中不可见,因为 People 没有可见类型。我上面概述的方法只有在类定义周围没有初始化块时才有效。

【讨论】:

  • 不,我们不能在 main 方法中这样做。 People 是本地类,只属于初始化块作用域。
  • 是的,你可以。我只是通过向 People 类添加一个方法并从 main 中的 person 对象调用它来(重新)测试它@
  • 换句话说,person 对象可以从main 访问,并且由于 OP 在main 中创建对象,我假设他想在那里使用它。
  • 如果 Person 类在初始化块中声明(如在 OP 示例中),则没有 Test.Person 类型。这就是为什么 OP 会问“这是否意味着 Initializer Block 不能用于定义类?”。您在回答中所说的很好,只需使用外部类的实例,而不是。这就是为什么 Jon Skeet 删除了他的第一个与你的相似的答案。
  • 啊,我现在明白了。我错过了那些额外的括号,使这个类只对初始化块本地化。谢谢
【解决方案5】:

是的,我们可以声明初始化块和 People 类的范围将在其中。更新代码如下:

  public class Test {
    {
        class People {  
             /// Stuff          
        }

        People people = new People(); // Create object of People
        System.out.println("Initializer block");
    }

    public static void main(String[] args) {
        Test obj = new Test();
    }
}

【讨论】:

  • 括号是故意的 - 根据问题的最后一句话,OP 尝试使用初始化程序块。
猜你喜欢
  • 2012-10-08
  • 1970-01-01
  • 2011-07-05
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 2012-01-10
  • 2014-09-04
  • 2019-04-07
相关资源
最近更新 更多