java - 私有(private)内部类的默认构造函数有形参吗?

标签 java language-design

警告 #1:这实际上是一个潜在的两部分:首先,私有(private)内部类的构造函数是否有形参?如果是,为什么 JLS 说没有?如果没有,如何/为什么不?

注意事项 #2:此问题不可用于推测。我只是在寻找权威答案。

默认构造函数在 JLS 8.8.9 中定义,其中(部分)声明:

The default constructor has no formal parameters, except in a non-private inner member class, where the default constructor implicitly declares one formal parameter representing the immediately enclosing instance of the class (§8.8.1, §15.9.2, §15.9.3).

(强调)

“非私有(private)”位对我来说似乎很奇怪:为了让内部类访问在其封闭类中定义的字段,它需要对该实例的引用。不管内部类是否是私有(private)的,这都应该是一样的。

事实上,javac 似乎同意我的观点,与规范相矛盾。如果我编译这个:

public class Ctors {
  private class MyInner {
  }
}

...然后运行 ​​javap -c -private,然后我们看到一个带有单个形式参数的构造函数,用于封闭类的实例:

$ javap -c -private Ctors\$MyInner
Compiled from "Ctors.java"
class Ctors$MyInner {
  final Ctors this$0;

  private Ctors$MyInner(Ctors);
    Code:
       0: aload_0
       1: aload_1
       2: putfield      #1        // Field this$0:LCtors;
       5: aload_0
       6: invokespecial #2        // Method java/lang/Object."<init>":()V
       9: return
}

供引用,这是在 Oracle JDK 1.8.0_05 上。

所以 JLS 说私有(private)内部成员类的默认构造函数没有形式参数,但 javac/javap 说它有一个。 (我对最自然的工作方式的理解也会说它应该有一个,因为它的值(value)很小。)哪个是正确的,为什么 JLS 专门排除私有(private)内部类?

最佳答案

实现和规范是有区别的。

在我看来,“除了”JLS 声明

...except in a non-private inner member class...

措辞不佳。

这意味着,编译器不需要隐式声明一个表示类的直接封闭实例的形式参数......但可以


为什么非私有(private)内部成员类需要隐式形参

来自 JLS 8.8.1 :

The member class may have been emitted by a compiler which is different than the compiler of the class instance creation expression. Therefore, there must be a standard way for the compiler of the creation expression to pass a reference (representing the immediately enclosing instance) to the member class's constructor

例如,如果我用第一个编译器编译这个内部类:

package p1;
public class Ctors {
    public class MyInner {
    }
}

如果我想用另一个编译器编译这个子类:

package p2;

import p1.Ctors;

public class SubCtors {
    public SubCtors() {
        new Ctors();
    }
}

第二个编译器必须能够使用带有形参的默认构造函数。 在这种情况下,带有 SubCtors 实例的封闭类的实例。


为什么非私有(private)内部成员类不需要隐式形参

因为非私有(private)内部成员类总是由编译它的同一个编译器访问。如您所示,javac 生成相同的构造函数,而不管类可见性如何,但这不是必需的。另一个编译器实现可以自由选择其他方式。

JLS 8.8.1 还有一点这是非常一致的

In a class instance creation expression for a local class (not in a static context) or anonymous class, §15.9.2 specifies the immediately enclosing instance of the local/anonymous class. The local/anonymous class is necessarily emitted by the same compiler as the class instance creation expression. That compiler can represent the immediately enclosing instance how ever it wishes. There is no need for the Java programming language to implicitly declare a parameter in the local/anonymous class's constructor.

关于java - 私有(private)内部类的默认构造函数有形参吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24896831/

相关文章:

java - Java 中的命令行(和多线程)

Java NoClassFoundDefError 和 ClassNotFoundException 问题

c++ - 关于状态机优化和代码生成的引用?

compiler-construction - 解决循环导入问题

c++ - 我可以在 C++ 中做/模仿这样的事情(部分覆盖)吗?

javascript - 原型(prototype)继承相对于经典继承的好处?

带有重复句点的java printf

java - 在android中对字符串数组列表进行排序

java - 如何从迭代器中获取 int[]?

c++ - 为什么只允许一个隐式转换将参数解析为 C++ 中的函数?