问题描述
package com.test;
public class OuterClass {
public class InnerClass {
public class InnerInnerClass {
}
}
public class InnerClass2 {
}
//this class should not exist in OuterClass after dummifying
private class PrivateInnerClass {
private String getString() {
return "hello PrivateInnerClass";
}
}
public String getStringFromPrivateInner() {
return new PrivateInnerClass().getString();
}
}
运行 javac
在命令行中使用 Sun JVM 1.6.0_20
,此代码生成6个.class文件:
When run through javac
on the command line with Sun JVM 1.6.0_20
, this code produces 6 .class files:
运行时在Eclipse中的JDT,它只产生5个类。
When run through JDT in eclipse, it produces only 5 classes.
反编译时, OuterClass $ 1.class
什么都不包含。这个额外的课程来自哪里,为什么会创建?
When decompiled, OuterClass$1.class
contains nothing. Where is this extra class coming from and why is it created?
推荐答案
我没有答案,但我能够确认,并将代码段减少到以下内容:
I don't have the answer, but I'm able to confirm that, and reduce the snippet to the following:
public class OuterClass {
private class PrivateInnerClass {
}
public void instantiate() {
new PrivateInnerClass();
}
}
这会创建 OuterClass $ 1。 class
Compiled from "OuterClass.java"
class OuterClass$1 extends java.lang.Object{
}
这里是 javap -c
for OuterClass.class
:
Compiled from "OuterClass.java"
public class OuterClass extends java.lang.Object{
public OuterClass();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public void instantiate();
Code:
0: new #2; //class OuterClass$PrivateInnerClass
3: dup
4: aload_0
5: aconst_null
6: invokespecial #3; //Method OuterClass$PrivateInnerClass."<init>":
//(LOuterClass;LOuterClass$1;)V
9: pop
10: return
}
对于 OuterClass $ PrivateInnerClass
:
Compiled from "OuterClass.java"
class OuterClass$PrivateInnerClass extends java.lang.Object{
final OuterClass this$0;
OuterClass$PrivateInnerClass(OuterClass, OuterClass$1);
Code:
0: aload_0
1: aload_1
2: invokespecial #1; //Method "<init>":(LOuterClass;)V
5: return
}
如您所见,合成的构造函数采用 OuterClass $ 1
参数。
As you can see, the synthesized constructor takes an OuterClass$1
argument.
所以 javac
创建默认构造函数以获取类型为 $ 1
的额外参数,以及该默认值参数是 5:aconst_null
。
So javac
creates the default constructor to take an extra argument, of type $1
, and the value of that default argument is 5: aconst_null
.
我发现如果满足以下任一条件,则无法创建 $ 1
:
I've found that $1
doesn't get created if either of the following is true:
- 您make
public class PrivateInnerClass
- 为
PrivateInnerClass
声明一个无效的构造函数li>
- 或者你不打电话给
新
- 可能还有其他事情(例如
static
嵌套等。)
- You make
public class PrivateInnerClass
- You declare a nullary constructor for
PrivateInnerClass
- Or you don't call the
new
on it - Probably other things (e.g.
static
nested, etc).
- :编译私有内部类会在错误的目录中创建一个匿名类文件
- Bug ID:4295934: Compiling a private inner class creates an anonymous class file in the wrong dir
package test;
public class testClass
{
private class Inner
{
}
public testClass()
{
Inner in = new Inner();
}
}
从父目录编译文件 javac test / testClass.java
请注意文件 testClass $ 1.class
在当前目录中创建。
不确定为什么甚至创建了这个文件,因为还创建了 test / testClass $ Inner.class
。
Notice that the file testClass$1.class
is created in the current directory. Not sure why this file is even created since there is also a test/testClass$Inner.class
created as well.
评估
testClass $ 1.class
文件适用于访问
构造函数所需的虚拟类,用于私有内部类的私有构造函数
testClass $ Inner
。 Dissassembly显示正确记录了该类的完全限定名
,因此不清楚为什么类文件在错误的目录中结束
。
The testClass$1.class
file is for a dummy class needed by an "access constructor" for the private constructor of the private inner class testClass$Inner
. Dissassembly shows that the fully-qualified name of this class is correctly noted, so it is unclear why the class file ends up in the wrong directory.
这篇关于为什么匿名内部类不包含从此代码生成的任何内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!