在java中,这样的类类型编译成啥?

Posted

技术标签:

【中文标题】在java中,这样的类类型编译成啥?【英文标题】:In java, what does such class type compile to?在java中,这样的类类型编译成什么? 【发布时间】:2015-09-20 00:27:42 【问题描述】:

下面是定义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&lt;annotationtype.Example&gt; class 静态成员变量。另外,这个成员变量Class&lt;annotationtype.Example&gt; class实际上指向了一个class Class类型的对象,它在class Example被加载到内存后维护class Example的元数据。

我的理解正确吗?

【问题讨论】:

我不确定您是否应该将 class 视为字段,因为就像 this 一样,它是 keyword,即使对于像 int.class 这样的原始类型,我们也可以使用它。但是如果你问的是classidea 那么是的,它可以以某种方式被视为在类中声明的静态字段。 @Pshemo,这可能是因为您总是可以使用Example.class,即引用static 成员,称为class。 :) 绝对不,javac 不会这样编译。您是否使用旧的反编译器来获取该代码? 我已经通过javap -p 输出。 @my-thoughts 请不要将Example.class 的字面意思转储到字节码中。请提供类似问题here中所示的功能翻译。 【参考方案1】:

如JLS 15.8.2 中所述,类文字是语言规范的一部分

类字面量是一个表达式,由类名、接口名、数组名或原始类型或伪类型 void 组成,后跟一个 '.'和令牌类。

C.class 的类型,其中 C 是类、接口或 数组类型(第 4.3 节),是 Class.

p.class 的类型,其中 p 是原始类型的名称(第 4.2 节), 是 Class,其中 B 是类型 p 的表达式的类型 拳击转换 (§5.1.7)。

void.class(第 8.4.5 节)的类型是 Class

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 中引用它时加载了该常量。

【讨论】:

@overexchange,这就是你想要的答案,+1。 您应该在回答中引用 JLS 的相关部分。 @uraimo 所以,我不应该按照Hello.class 的语法去解释classclass Hello 的成员。我想解释为,javacHello.class 语法解释为特殊语法并提供相应的字节码来创建class Class 类型的对象,myClass 指向该对象。对吗? 是的,正确的。你在 Hello 类的常量池中看到 #2 = Class #21 // Hello 了吗?这是javac 所做工作的结果,它将一个类常量添加到.class 文件的常量池中,并将其与ldc #2 字节码一起使用(ldc=load constant from constantpool)。 1) 如果您的意思是实习字符串,不,那是字符串池,如果您的意思是从 javac 生成的 .class 文件加载的字符串文字,是的。 2)我指的是你在上面看到的#2 = Class,从这个问题中了解更多关于常量池的信息:***.com/questions/10209952/…【参考方案2】:

如果“功能编译”是指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)
    

【讨论】:

如果反汇编代码中没有成员class,为什么java允许你说Example.class @overexchange 因为类文字是语言规范的一部分 JLS 15.8.2

以上是关于在java中,这样的类类型编译成啥?的主要内容,如果未能解决你的问题,请参考以下文章

Java反射机制

JavaWeb的实体类定义中一般日期定义成啥格式?

在java中创建一个类的时候,如果前面不写public ,那么这个类会被默认成啥类型?

Java千百问_05面向对象(014)_如何获取范型的类Class

java中import的作用

Android编译时动态替换Jar包中的类