私有内部类的默认构造函数是否具有形式参数? [英] Do default constructors for private inner classes have a formal parameter?

查看:144
本文介绍了私有内部类的默认构造函数是否具有形式参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Caveat #1: This is actually a potential two-parter: First, does the constructor for a private inner class have a formal parameter? If yes, why does the JLS say it doesn't? And if no, how/why not?

警告#2:这个问题不适合猜测。我正在寻找权威的答案。

Caveat #2: This question is not for speculation. I'm looking for authoritative answers only.

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

Default constructors are defined in JLS 8.8.9, which states (in part):


默认构造函数没有形式参数,但非私有内部成员类除外,其中默认构造函数隐式声明一个形式参数,表示该类的直接封闭实例(§8.8。 1,§15.9.2,§15.9.3)。

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).

(强调添加)

非私有位对我来说似乎很奇怪:为了让内部类访问其封闭类中定义的字段,它需要对该实例的引用。无论内部类是否是私有的,这都应该是相同的。

The "non-private" bit seems odd to me: in order for an inner class to access fields defined in its enclosing class, it needs a reference to that instance. This should be the same regardless of whether the inner class is private.

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

In fact, javac seems to agree with me, in contradiction to the spec. If I compile this:

public class Ctors {
  private class MyInner {
  }
}

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

...and run javap -c -private, then we see a constructor with a single formal parameter, for the instance of the enclosing class:

$ 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上。

For reference, this is on Oracle JDK 1.8.0_05.

所以JLS说私有内部成员类的默认构造函数没有正式参数,但是javac / javap说它有一个。 (我对最自然的工作方式的理解也会说它应该有一个,对于那些值得的东西。)哪个是正确的,为什么JLS明确排除私人内部类?

So the JLS says that the default constructor for private inner member classes has no formal parameters, but javac/javap say it has one. (My understanding of the most natural way for things to work would also say it should have one, for the little that's worth.) Which is right, and why does the JLS specifically exclude private inner classes?

推荐答案

实施与规范之间存在差异。

There is a difference between the implementation and the specification.

在我看来除外 JLS声明

In my opinion the "except" JLS statement


... 非私有内部成员类中的 ......

措辞不佳。

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

It means, the compiler is not required to implicitly declares one formal parameter representing the immediately enclosing instance of the class... but it could.

为什么非必需隐式形式参数 私人内部成员类?

Why implicitly formal parameter is required in non-private inner member class ?

来自 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

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

For example if i compile this inner class with a first compiler:

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

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

if i want to compile this sub class with another compiler:

package p2;

import p1.Ctors;

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

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

the second compiler must be able to use the default constructor with the formal parameter. In this case the instance of the enclosing class with a SubCtors instance.

为什么非私有内部成员类中隐式正式参数不需要

Why implicitly formal parameter is not required in non-private inner member class ?

因为非私有内部成员类始终由编译它的同一编译器访问。如图所示,无论类可见性如何,javac都会生成相同的构造函数,但不需要。另一个编译器实现可以自由选择另一种方式。

Because a non-private inner member class is always accessed by the same compiler that compiled it. As you shown, javac generates the same constructor regardless to the class visibility but it is not require to. Another compiler implementation is free to choose another way.

JLS 8.8.1 这是非常相同的行


本地类(不在静态上下文)或匿名类的类实例创建表达式中,§15.9.2指定本地/匿名类的直接封闭实例。本地/匿名类必须由与类实例创建表达式相同的编译器发出。该编译器可以表示它所希望的直接封闭的实例。 Java编程语言不需要在local / anonymous类的构造函数中隐式声明参数。

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.

这篇关于私有内部类的默认构造函数是否具有形式参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆