当我浏览java内部类时,我读到了编译器为内部类创建一个单独的.class文件,该文件是$ .class格式。 后来我发现对于每个外部类构造函数,它都会创建一个单独的.class文件,该文件位于$ 1.class中。
为什么编译器也为构造函数执行此操作?我想知道构造函数和内部类之间是否存在任何关系。
public class Foo
{
Foo()
{
System.out.print("foo");
}
class Bar
{
Bar()
{
System.out.print("bar");
}
public void go()
{
System.out.print("hi");
}
} /* class Bar ends */
public static void main (String [] args)
{
Foo f = new Foo();
f.makeBar();
}
void makeBar()
{
(new Bar() {}).go();
}
}
答案 0 :(得分:1)
因为这个问题再次打开,我会尝试在评论中回答。
此编译器行为来自其他内容。
这是因为您正在Bar
类(new Bar() {})
进行扩展(创建匿名扩展类)。而且因为这个课程是匿名的在Foo
类内,它的名称为Foo$1.class
反编译的类看起来像这样:
<强>富$ 1.class 强>
class Foo$1 extends r
{
final Foo this$0;
Foo$1()
{
this$0 = Foo.this;
super(Foo.this);
}
}
我使用了JAD反编译器。 extends r
是因为JAD对超级课程一无所知。
如果您修改代码如下:
void makeBar() {
(new Bar() {
public void test() { // added method
System.out.println("It's alive!");
}
}).go();
}
反编译的Foo $ 1.class看起来像这样:
class Foo$1 extends r
{
public void test()
{
System.out.println("It's alive!");
}
final Foo this$0;
Foo$1()
{
this$0 = Foo.this;
super(Foo.this);
}
}
证明Foo $ 1.class是扩展到位(匿名)Bar
类。
答案 1 :(得分:1)
让我们看看您的代码:
public class Foo
{
Foo() // Constructor of Foo
{
System.out.print("foo");
} // End of Constructor for Foo
class Bar // Inner class Bar
{
Bar() // Constructor of Bar
{
System.out.print("bar");
} // End of constructor for Bar
public void go()
{
System.out.print("hi");
}
} // End of inner class Bar
public static void main (String [] args)
{
Foo f = new Foo();
f.makeBar();
}
void makeBar()
{
(new Bar() {}).go(); // Anonymous class inheriting from Bar
}
}
所以你得到的三个类文件是:
Foo.class
Foo$Bar.class
makeBar
- Foo$1.class
所以你看,这与构造函数无关。它只与在类中创建的实际类有关。匿名类创建一个class
文件就像一个命名的内部类 - 但命名约定是一个数字跟在$
符号后面而不是类的名称,因为它是匿名的。 / p>
您可以轻松地将makeBar
方法中的代码更改为:
void makeBar()
{
new Bar().go();
}
这将消除匿名类,为您提供相同的输出,但只创建两个class
文件。所以它与构造函数无关。