此外, 只有基本数据类型或String类型的静态变量才可以存在ConstantValue属性, 原因在下面会有说明。
下面介绍它的结构:
attribute_name_index和attribute_length就不过多介绍了, 和上面介绍的是一样的。这里的attribute_length为2 。
位于attribute_length之下的是constantvalue_index , 这是一个指向常量池中某个数据项的索引。这个常量池数据项中存放的就是当前字段的值。
这个常量池中的数据项,根据field_info描述的字段的不同, 可以是不同类型的数据项, 如果当前字段是byte, short, char, int, boolean类型, 那么这个被指向的常量池数据项就会是一个CONSTANT_Integer_info , 如果当前字段是一个long类型的字段, 那么这个被指向的常量池数据项就会是一个CONSTANT_Long_info 。 如果当前字段是是一个String类型的字段 , 那么这个被指向的常量池数据项就是一个CONSTANT_String_info 。 这里有一点需要说明, 虽然java语言支持byte, short, char, boolean类型, 但是JVM却不支持这几种类型, 表现在class文件中就是, class文件中的常量池中没有和这几个数据类型相对应的数据项, 这几中类型都被JVM在执行时当做int来对待, 表现在class文件中就是, 这几种类型都对应常量池中的CONSTANT_Integer_info 数据项。
这也说明了, 为什么只有基本数据类型和String类型的静态常量才会存在ConstantValue属性 。 因为constantvalue_index只是一个指向常量池的索引, 而其他引用类型的常量不会存在于常量池中。
下面以实例来说明, 实例代码如下:
package com.jg.zhang;
public class Person {
static final int a = 1;
int age;
int getAge(){
return age;
}
}
反编译后的相关结果如下:
......
Constant pool:
#7 = Utf8 ConstantValue
#8 = Integer 1
{
static final int a;
flags: ACC_STATIC, ACC_FINAL
ConstantValue: int 1
.........
}
可以看到, 源文件中的a字段, 是static final 的, 所以编译器为这个字段的filed_info生成了ConstantValue属性。 这个属性的示意图如下所示, 注意, 虚线范围内表示常量池区域:
Deprecated属性
Deprecated属性可以存在于filed_info中, method_info中和顶层的ClassFile中, 分别表示这个字段, 方法或类已经过时。 这个属性用来支持源文件中的@deprecated注解。 也就是说, 如果在源文件中为一个字段, 方法或类标注了@deprecated注解, 那么编译器就会在class文件中为这个字段, 方法或类生成一个Deprecated属性 。
Deprecated属性的格式如下:
和上面的属性一样, attribute_name_index属性指向一个常量池中的CONSTANT_Utf8_info 。 这个CONSTANT_Utf8_info中存放着该属性的名字 “Deprecated” 。
attribute_length永远为0 , 因为这个属性只是一个标志信息, 用来表示字段, 方法, 类已经过时, 而不具有任何实质性的属性信息。
下面以代码示例来说明, 代码如下:
package com.jg.zhang;
public class Person {
int age;
@Deprecated
int getAge(){
return age;
}
}
在getAge方法上使用了@deprecated 。 下面是反编译之后的相关信息:
......
Constant pool:
......
#18 = Utf8 Deprecated
......
{
......
int getAge();
flags:
Deprecated: true
......
}
可以看到, 在getAge方法相关的信息中, 有一行 Deprecated: true , 这说明编译器在getAge方法的method_info中加入了Deprecated属性。 常量池第18项的CONSTANT_Utf8_info中存放的是Deprecated属性的属性名“Deprecated” 。
下面是示意图, 虚线范围内表示常量池区域:
总结
本文就到此为止。 在本文中, 主要讲解了class文件中的一些属性。 这些属性可以出现在class文件中的对个地方, 用来描述一些其他信息。
在下一篇博客中, 会继续讲解其他属性。 下一篇博客要讲解的属性相对比较重要, 因为这些属性主要是和方法相关的。 到目前为止, 我们已经讲解了class文件中的大部分信息, 包括常量池, this_class, super_class, field_info, method_info等等。 虽然method_info是对一个方法的描述, 但是目前我们知道的而关于method_info的信息, 只描述了方法的方法名, 描述符等签名信息。 但是方法中还包括很多重要信息, 比如字节码指令, 异常处理块, 方法声明抛出的异常 等。 这些重要信息在class文件中是如何描述的呢? 下一篇博客将会揭晓答案, 敬请关注。
更多关于深入理解Java的文章, 请关注我的专栏 : http://blog.csdn.net/column/details/zhangjg-java-blog.html
更多关于Java和Android等其他技术的文章, 请关注我的博客: http://blog.csdn.net/zhangjg_blog