class Outer
{
int outer_x = 100;
void test()
{
for(int i=0; i<10; i++)
{
class Inner
{
void display()
{
System.out.println("display: outer_x = " + outer_x);
}
}
Inner inner = new Inner();
inner.display();
}
}
}
当我调用test()时,将创建内部类的次数,它是十次还是只创建一次并创建了10个对象?还要告诉你如何得出这个结论。
答案 0 :(得分:1)
编译代码时,类Inner
只创建一次,如@EJP所述。在查看编译输出时,您可以轻松验证这一点。
我创建了一个名为Outer.java
的.java文件,并简单地编译它。结果是两个.class文件。
您可以看到编译器创建了一个名为Outer.class
的类文件,但也创建了一个名为Outer$1Inner.class
的类文件,它只是您的本地类。在这里,Java使用$1
来标记内部匿名类。
添加main
方法并调用new Outer().test();
,您可以看到输出确实是10行,这意味着创建了10个实例 Inner
。您可以通过在输出中的某处添加hashCode()
来轻松验证这一点
System.out.println("display: outer_x = " + outer_x + " --> " + hashCode());
其中给出了以下输出:
display: outer_x = 100 --> 1704856573
display: outer_x = 100 --> 705927765
display: outer_x = 100 --> 366712642
display: outer_x = 100 --> 1829164700
display: outer_x = 100 --> 2018699554
display: outer_x = 100 --> 1311053135
display: outer_x = 100 --> 118352462
display: outer_x = 100 --> 1550089733
display: outer_x = 100 --> 865113938
display: outer_x = 100 --> 1442407170
不同的哈希码意味着不同的实例。
现在发生这一切,因为编译器在收集类时并不关心像for
这样的控制流语句。它看到内部类并编译一次。另一方面,输出发生在运行时,并遵循控制流语句。
答案 1 :(得分:0)
该类仅创建一次。除了能够查看生成的类文件的实现细节之外,您还可以通过打印类的ID来显示它是相同的Class对象:
for (int i = 0; i < 10; i++) {
class Inner {
void display() {
System.out.println("display: outer_x = " + outer_x);
}
}
Inner inner = new Inner();
System.out.println(System.identityHashCode(inner.getClass()));
inner.display();
}
每次打印相同的数字。
但是如果你对它进行编码,那么每次在循环中你创建了一个行为不同的类呢?
for (int i = 0; i < 10; i++) {
class Inner {
private int field = i;
void display() {
System.out.println("My field = " + field);
}
}
}
这不会编译,因为 Java只会创建一个类,所以每次都必须相同。
编译错误是:local variables referenced from an inner class must be final or effectively final
,因为i
不是final
,编译器也不能将其视为final
。如果变量是final,那么每次迭代时类都是相同的。