在java中,这种类类型编译为什么?

时间:2015-07-02 12:51:42

标签: java reflection compilation

以下是定义class类型的代码:

package annotationtype;

public class Example {

    public static void main(String[] args){


    }
}

javac功能编译为:

public class annotationtype.Example{
    public static Class<annotationtype.Example> class;
    {
        class = Class.forName("annotationtype.Example")
    }
    public annotationtype.Example(){}
    public static void main(java.lang.String[] args){}
}

我主要关注上面代码中的Class<annotationtype.Example> class静态成员变量。此外,此成员变量Class<annotationtype.Example> class实际上指向class Class类型的对象,该对象在class Example加载到内存后维护class Example的元数据。

我的理解是否正确?

2 个答案:

答案 0 :(得分:4)

类文字是JLS 15.8.2

中提到的语言规范的一部分
  

类文字是一个表达式,由类,接口,数组或基本类型的名称或伪类型void组成,后跟“。”。和令牌类。

     

C.class的类型,其中C是类,接口或的名称   数组类型(§4.3),是Class&lt; C&gt;。

     

p.class的类型,其中p是基本类型的名称(§4.2),   是Class&lt; B&gt ;,其中B是p后面的类型的表达式   拳击转换(§5.1.7)。

     

void.class(§8.4.5)的类型是Class&lt; Void&gt ;.

javac不会为每个类创建静态class字段,但它会识别一个类文字表达式并正确编译它。

以课程为例:

public class Hello {
        public static void main(String[] args){
                Class<?> myClass = Hello.class;
                System.out.println("Hello, " + myClass);
        }
}

这编译为(仅包含字节码的相关部分):

public class Hello   minor version: 0   major version: 52   flags:
 ACC_PUBLIC, ACC_SUPER 
Constant pool:    
#1 = Methodref          #11.#20        // java/lang/Object."<init>":()V    
#2 = Class              #21            // Hello
......
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
  stack=3, locals=2, args_size=1
     0: ldc           #2                  // class Hello
     2: astore_1

你可以看到javac在常量池中引用了Hello类,然后在main中引用它时加载了该常量。

答案 1 :(得分:0)

如果通过“功能编译”表示您可以使用class“字段”而没有明确声明它,那么您是正确的。当然,class不是字段,它是java语言中的类文字。

此外,如果我们编译javac Example.java然后解析javap -c Example我们就会留下这个:

Compiled from "Example.java"
public class Example {
  public Example();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: return
}

请注意,此解密代码中没有class的引用。另一方面,默认构造函数Example()神奇地显示出来,可以说是

public class Example {
    public static void main(String[] args){
    }
}

编译到

public class Example {
    public Example(){}
    public static void main(String[] args){
    }
}