本文介绍了为什么匿名内部类不包含从此代码生成的任何内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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.

这篇关于为什么匿名内部类不包含从此代码生成的任何内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-29 08:29