在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<annotationtype.Example> class
静态成员变量。另外,这个成员变量Class<annotationtype.Example> class
实际上指向了一个class Class
类型的对象,它在class Example
被加载到内存后维护class Example
的元数据。
我的理解正确吗?
【问题讨论】:
我不确定您是否应该将class
视为字段,因为就像 this
一样,它是 keyword
,即使对于像 int.class
这样的原始类型,我们也可以使用它。但是如果你问的是class
的idea 那么是的,它可以以某种方式被视为在类中声明的静态字段。
@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
的语法去解释class
是class Hello
的成员。我想解释为,javac
将Hello.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中创建一个类的时候,如果前面不写public ,那么这个类会被默认成啥类型?