Java class文件格式之属性详解

合集下载

java中类的用法

java中类的用法

java中类的用法Java是一种面向对象的编程语言,类是面向对象编程的基本概念之一。

在Java中,类是一种模板,它用来描述一类对象的方法和属性。

可以通过创建类的对象来使用它的方法和属性。

本文将介绍Java中类的用法。

一、定义类Java中定义类的语法如下:```java public class ClassName { // 类的成员变量 // 类的构造函数 // 类的方法 } ```其中,类名要遵循标识符的命名规范。

类的成员变量是类的属性,它们用于存储对象的状态。

类的构造函数用于创建对象并初始化它的成员变量。

类的方法用于定义对象的行为。

二、成员变量Java中的成员变量也称为类的属性,用于存储对象的状态。

成员变量可以是基本类型、引用类型或数组类型。

在类的定义中,成员变量要放在构造函数和方法的前面。

成员变量可以通过类的对象来访问和修改。

```java public class Person { private String name; private int age;public Person(String name, int age){ = name; this.age = age; }public String getName() { return name; }public void setName(String name){ = name; }public int getAge() { return age; }public void setAge(int age){ this.age = age; } } ```在上面的例子中,Person类有两个成员变量name和age,它们都使用private关键字修饰,表示只能在类内部访问。

同时,这个Person类提供了一个有参构造函数和getter、setter方法,用来访问和修改成员变量。

三、构造函数Java中的构造函数用于创建对象并初始化它的成员变量。

Java class文件格式之数据类型(二)

Java class文件格式之数据类型(二)

Java class文件格式之数据类型(二)常量池中各数据项类型详解(续)(8) CONSTANT_Class_info常量池中的一个CONSTANT_Class_info,可以看做是CONSTANT_Class数据类型的一个实例。

他是对类或者接口的符号引用。

它描述的可以是当前类型的信息,也可以描述对当前类的引用,还可以描述对其他类的引用。

也就是说,如果访问了一个类字段,或者调用了一个类的方法,对这些字段或方法的符号引用,必须包含它们所在的类型的信息, CONSTANT_Class_info就是对字段或方法符号引用中类型信息的描述。

CONSTANT_Class_info的第一个字节是tag,值为7,也就是说,当虚拟机访问到一个常量池中的数据项,如果发现它的tag值为7,就可以判断这是一个CONSTANT_Class_info 。

tag下面的两个字节是一个叫做name_index的索引值,它指向一个CONSTANT_Utf8_info,这个CONSTANT_Utf8_info中存储了CONSTANT_Class_info要描述的类型的全限定名。

此外要说明的是,java中数组变量也是对象,那么数组也就有相应的类型,并且数组的类型也是使用CONSTANT_Class_info描述的,并且数组类型和普通类型的描述有些区别。

普通类型的CONSTANT_Class_info中存储的是全限定名,而数组类型对应的CONSTANT_Class_info中存储的是数组类型相对应的描述符字符串。

举例说明:与Object类型对应的CONSTANT_Class_info中存储的是:java/lang/Object与Object[]类型对应的CONSTANT_Class_info中存储的是:[Ljava/lang/Object;下面看CONSTANT_Class_info的存储布局:例如,如果在一个类中引用了System这个类,那么就会在这个类的常量池中出现以下信息:(9) CONSTANT_Fieldref_info常量池中的一个CONSTANT_Fieldref_info,可以看做是CONSTANT_Field数据类型的一个实例。

java项目文件结构描述格式

java项目文件结构描述格式

java项目文件结构描述格式当我们开始一个新的Java项目时,良好的文件结构是非常重要的。

一个清晰的文件结构可以让我们更容易地组织和管理代码,提高团队协作效率,同时也方便新成员快速熟悉项目结构。

下面是一个常见的Java项目文件结构描述格式:1. src,源代码目录。

main,主要源代码目录。

java,Java源文件目录。

com,包名。

example,示例。

MyClass.java,Java类文件。

resources,资源文件目录。

config,配置文件目录。

static,静态资源文件目录。

templates,模板文件目录。

test,测试源代码目录。

java,测试Java源文件目录。

com,包名。

example,示例。

MyClassTest.java,测试类文件。

resources,测试资源文件目录。

2. lib,依赖库目录。

jar,第三方JAR包。

native,本地库文件。

3. build,构建输出目录。

classes,编译后的class文件。

libs,打包后的JAR文件。

4. docs,文档目录。

design,设计文档。

api,API文档。

readme.md,项目说明文档。

5. config,配置文件目录。

application.properties,应用配置文件。

log4j.properties,日志配置文件。

6. .gitignore,Git忽略文件配置。

7. README.md,项目说明文档。

8. pom.xml,Maven项目配置文件。

9. build.gradle,Gradle项目配置文件。

以上是一个常见的Java项目文件结构描述格式,当然在实际项目中可能会根据具体需求有所不同。

然而,一个清晰的文件结构可以让我们更好地管理项目,提高代码质量和团队协作效率。

希望这个文件结构描述能够帮助到你。

Java类的属性与方法 PPT

Java类的属性与方法 PPT

方法调用
• 方法是个“黑匣子”,完成某个特定的应用程序功能,并返回结果 • 方法调用:执行方法中包含的语句
对象名.方法名();
小明过生日,爸爸送他一个电动狮子玩具,编程测试这个狮子能否正常工作
方法调用
public class LionTest { public static void main(String[ ] args) {
类的方法
按此按钮, 狮子开始跑
电动玩具狮子 属性: 颜色:黄色
行为: 跑 叫
• 写出狮子对象的“跑”方法 • 写出狮子对象的“叫”方法
类的方法示例
AutoLion类代码实现
访问类型
public class Au返to回Lio类n型{ String color = "黄色";
方法名称
public void run(){ System.out.println("正在以0.1米/秒的速度向前奔跑");
Phone Student= new Student() ;
12
public Student()
{
}
方法的主体
方法的命名
• 如何给方法起名字? – 只能以字母、‘_’或‘$’开头 – 可以包括数字,但不能以它开头
• 遵循的命名规范 – 通常方法名是一个动词,如果有两个以上单词组成,第一个单词的种情况 – 如果方法具有返回值,方法中必须使用关键字return返回该值,返回类型为该返回 值的类型
} }
方法调用案例
• 编写成绩计算类(ScoreCalc) • 编写测试类
成绩计算类 测试类
编程实践
– 编写手机类(Phone):它可以下载音乐,可以播放这些音乐,可以进行充电

java class 指令部分

java class 指令部分

java class 指令部分Java Class指令是用于定义类的关键指令。

在Java中,每个类都必须使用class关键字进行定义。

本文将详细介绍Java Class指令的使用方法和注意事项。

一、Java Class指令的基本语法在Java中,使用class关键字定义类。

其基本语法如下所示:```[访问修饰符] class 类名 {// 类的成员变量和方法}```其中,访问修饰符可以是public、private、protected或默认的包级访问权限。

类名是标识符,遵循命名规则,且首字母大写。

二、Java Class指令的使用方法1. 定义类的成员变量:在类中使用变量声明语句定义类的成员变量。

可以使用不同的数据类型,如int、double、String等。

2. 定义类的方法:在类中使用方法声明语句定义类的方法。

方法可以有不同的访问修饰符和返回值类型,可以有参数列表和方法体。

3. 创建类的对象:在类外部使用new关键字创建类的对象,并调用对象的方法或访问对象的成员变量。

三、Java Class指令的注意事项1. 类名必须与文件名相同,并且扩展名为.java。

2. 一个源文件中可以定义多个类,但只能有一个public类。

3. 类的成员变量和方法可以使用不同的访问修饰符,以控制对其的访问权限。

4. 类的成员变量通常使用private修饰,通过公有的get和set方法来访问和修改。

5. 类的方法可以通过重载和重写来实现不同的功能。

6. 类的构造方法在创建对象时自动调用,用于初始化对象的成员变量。

7. 类的继承使用extends关键字,子类可以继承父类的成员变量和方法。

8. 类的多态性通过接口和抽象类来实现,提高了代码的灵活性和可维护性。

四、Java Class指令的示例代码下面是一个简单的示例代码,演示了Java Class指令的使用方法:```javapublic class Person {private String name;private int age;public Person(String name, int age) { = name;this.age = age;}public void sayHello() {System.out.println("Hello, my name is " + name + ", I am " + age + " years old.");}public static void main(String[] args) {Person person = new Person("T om", 20);person.sayHello();}}```以上代码定义了一个Person类,包含了成员变量name和age,以及构造方法和sayHello方法。

Java语言中的Class类

Java语言中的Class类

Java语⾔中的Class类基本概念在Object类中定义了以下的⽅法,此⽅法将被所有⼦类继承public final Class getClass()这个⽅法的返回值类型是⼀个Class类,此类是Java反射的源头,是实际上所谓反射从程序的运⾏结果来看也很好理解,即:可以通过对象反射求出类的名称。

对象照镜⼦后可以得到的信息:某个类的属性、⽅法和构造器、某个类到底实现了哪些接⼝。

对于每个类⽽⾔,JRE都为其保留⼀个不变的Class类型的对象。

⼀个Class对象包含了特定某个结构(class、interface、enum、annotation、primitive type、void)的有关信息。

Class本⾝也是⼀个类Class对象只能由系统建⽴对象⼀个加载的类在JVM中只会有⼀个Class实例⼀个Class对象对应的是⼀个加载到JVM中的⼀个.class⽂件每个类的实例都会记得⾃⼰是由哪个Class实例所⽣成通过Class可以完整地得到⼀个类中的所有被加载结构Class类是Reflection的根源,针对任何你想动态加载、运⾏的类,唯有先获得相应的Class对象。

Java中拥有Class对象的类型在Java语⾔中,⼀切皆是对象。

⽽对象主要分为两种,⼀种是普通类创建的实例对象,⼀种是Class类对象。

每个类运⾏时的类型信息就是通过Class对象表⽰的,这个对象包含了与类有关的信息。

其实Java中的实例对象就是通过Class对象来创建的,Java使⽤Class对象执⾏其RTTI(运⾏时类型识别,Run-Time Type Identification),多态是基于RTTI实现的。

那么在Java中哪些类型可以有Class对象呢?class:外部类、成员(成员内部类、静态内部类)、局部内部类、匿名内部类interface:接⼝[]:数组enum:枚举annotation:注解@interfaceprimitive type:基本数据类型void我们⽤代码演⽰⼀下,这些类型的Class对象都是什么?Class c1 = Object.class; // 类Class c2 = Comparable.class; // 接⼝Class c3 = String[].class; // ⼀维数组Class c4 = int[][].class; // ⼆维数组Class c5 = Override.class; // 注解Class c6 = ElementType.class; // 枚举Class c7 = Integer.class; // 基本数据类型(包装类)Class c10 = int.class; // 基本数据类型Class c8 = void.class; // 空类型Class c9 = Class.class; // ClassSystem.out.println(c1); // class ng.ObjectSystem.out.println(c2); // interface parableSystem.out.println(c3); // class [ng.String;System.out.println(c4); // class [[ISystem.out.println(c5); // interface ng.OverrideSystem.out.println(c6); // class ng.annotation.ElementTypeSystem.out.println(c7); // class ng.IntegerSystem.out.println(c10);// intSystem.out.println(c8); // voidSystem.out.println(c9); // class ng.Classint[] a = new int[10];int[] b = new int[100];/*对于数组,只要元素类型与维度⼀样,就是同⼀个Class对象*/System.out.println(a.getClass()); //class [ISystem.out.println(b.getClass()); //class [ISystem.out.println(b.getClass().hashCode()); //1735600054System.out.println(a.getClass().hashCode()); //1735600054每⼀个类都有⼀个Class对象,每当编译⼀个新类就产⽣⼀个Class对象,更准确的来说,是被保存在⼀个同名的.class⽂件中。

Java的class是什么意思

Java的class是什么意思

一、class类有什么用?
class类的实例表示Java应用运行时的类(class ans enum)或接口(interface and annotation)(每个java类运行时都在JVM里表现为一个class对象,可通过类名.class,类型.getClass(),Class.forName("类名")等方法获取class对象)。

数组同样也被映射为为class 对象的一个类,所有具有相同元素类型和维数的数组都共享该Class 对象。

基本类型boolean,byte,char,short,int,long,float,double和关键字void同样表现为class 对象。

二、class类的特征
class类没有公有的构造方法,它由JVM自动调用(在new对象或者加载-classLoader 时)。

下面的方法作用是打印出对象的class name:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
同样可以根据class literal 获得class name:
System.out.println("The name of class Foo is: "+Foo.class.getName());//你可以将Foo改为void尝试下。

class文件与dex文件解析

class文件与dex文件解析

class⽂件与dex⽂件解析关于Android的热修复与插件化技术在如今基本上已经成为了“时髦技术”的标配了,或者说⽤来进⾏“炫技”的⼀种⽅式,毕境如今Android已经发展得⾮常之成熟了,基本上APP⽤的到东东都差不多,除了业务不同之外,但是!对于热修复与插件化并不是每个公司或者每个程序员愿意去应⽤到商⽤项⽬上的,因为既使不加它貌似对传统APP 的开发也⽊有啥影响,毕境加它还是有些繁锁的,⽽不管有没有在商⽤APP上去集成过它们,并不影响它被众多开发者所追捧,如今去⾯个试我想被问到热修复与插件化相关的技术问题应该只多不少,⽽且还得让你去对它底层的原理进⾏⼀些阐述,如果不需要⾯试也得有必要去掌握这⼀技术,因为毕境能集成到⾃⼰的APP上是能够实际解决APP的⼀些问题的,基于此有必要系统的去探究,彻底掌握它们,所以接下来会从基础开始⼀点点去揭开它神秘的⾯纱。

对于Dex⽂件是能够在Android被执⾏的⼀种格式,⽽它是由class⽂件进⾏演变过来的,在android的热修复中是需要涉及到Dex⽂件之间的⼀个diff操作的,⽽它的基础就是得对其⽂件结构有⼀定的了解,所以这⾥基础就先来熟悉⼀下⽂件结构。

class⽂件解析:什么是class⽂件:能够被JVM识别,加载并执⾏的⽂件格式。

如何⽣成⼀个class⽂件:是不是只有java⽂件才能够⽣成class⽂件呢?其实不是的,看下⾯这张图就晓得了:对于class⽂件的⽣成⼀般是由两种⽅式来完成的:IDE⾃动⽣成、javac命令,这⾥主要是演⽰⼀下javac命令的⽅式,对于它在我们学习j2se的时候已经经历过了,这⾥再来温故⼀下:新建⼀个最简单的java⽂件,⾥⾯内容如下:然后编译⽣成class字节码⽂件:然后运⾏:另外对于javac命令还可以指令编译的JDK版本,如下:class⽂件的作⽤:⽤⼀句话描述:“记录⼀个类⽂件的所有信息”,class⽂件的信息是远远多于java源代码的信息的,⽐如说我们在写java代码时并没有定义"this"、"super"关键字,但是确能够使⽤它们去调⽤当前类的⽅法或⽗类的⽅法,这是因为在⽣成class字节码⽂件的时候JVM帮我们记录了this和super关键字,所以从这点也能体会到class字节码⽂件的信息要远远多于Java源代码所看到的信息。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Java class文件格式之属性详解
Code属性
code属性是方法的一个最重要的属性。

因为它里面存放的是方法的字节码指令,除此之外还存放了和操作数栈,局部变量相关的信息。

所有不是抽象的方法,都必须在method_info中的attributes中有一个Code属性。

下面是Code 属性的结构,为了更直观的展示Code属性和method_info的包含关系,特意画出了method_info:
下面依次介绍code属性中的各个部分。

attribute_name_index指向常量池中的一个CONSTANT_Utf8_info ,这个CONSTANT_Utf8_info 中存放的是当前属性的名字“Code” 。

attribute_length给出了当前Code属性的长度(不包括前六字节)。

max_stack指定当前方法被执行引擎执行的时候,在栈帧中需要分配的操作数栈的大小。

max_locals指定当前方法被执行引擎执行的时候,在栈帧中需要分配的局部表量表的大小。

注意,这个数字并不是局部变量的个数,因为根据局部变量的作用域不同,在执行到一个局部变量以外时,下一个局部变量可以重用上一个局部变量的空间(每个局部变量在局部变量表中占用一个或两个Slot)。

方法中的局部变量包括方法的参数,方法的默认参数this,方法体中定义的变量,catch语句中的异常对象。

关于执行引擎的相关内容会在后面的博客中讲到。

code_length指定该方法的字节码的长度,class文件中每条字节码占一个字节。

code存放字节码指令本身,它的长度是code_length个字节。

exception_table_length指定异常表的大小
exception_table就是所谓的异常表,它是对方法体中try-catch_finally的描述。

exception_table可以看做是一个数组,每个数组项是一个exception_info结构,一般来说每个catch块对应一个exception_info,编译器也可能会为当前方法生成一些exception_info。

exception_info的结构如下(为了直观的显示exception_info, exception_table和Code属性的关系,画出了Code属性,的话读者就会更清楚各个数据项之间的位置关系和包含关系):
下面讲解exception_info中的各个字段的意思。

start_pc是从字节码(Code属性中的code部分)起始处到当前异常处理器起始处的偏移量。

end_pc是从字节码起始处到当前异常处理器末尾的偏移量。

handler_pc是指当前异常处理器用来处理异常(即catch块)的第一条指令相对于字节码开始处的偏移量。

catch_type是一个常量池索引,指向常量池中的一个CONSTANT_Class_info数据项,该数据项描述了catch块中的异常的类型信息。

这个类型必须是ng.Throwable的或其子类。

所以可以总结,一个异常处理器(exception_info)的意思是:如果偏移量从start_pc到end_pc之间的字节码出现了catch_type描述的类型的异常,那么就跳转到偏移量为handler_pc的字节码处去执行。

如果catch_type为0,就代表不引用任何常量池项(再回顾一下,常量池中的项是从1开始计的),那么这个exception_info用于实现finally子句。

我们一直在介绍Code属性,只不过刚才进行了一个小插曲,介绍了Code属性中的exception_table中的exception_info 的详细信息。

下面我们继续介绍Code 属性中的其他信息,希望读者不要被绕晕了: )
attributes_count 表示当前Code 属性中存在的其他属性的个数。

现在我们知道,class中的属性,不仅会出现在顶层的class中,会存在field_info中,会存在method_info中,甚至还会出现在属性中。

attributes可以看做是一个数组,里面存放了Code属性中的其他属性。

Code 属性中可以出现的其他属性有LineNumberTable和LocalVariableTable 。

这两个属性会在下面介绍。

LineNumberTable属性
LineNumberTable属性存在于Code属性中,它建立了字节码偏移量到源代码行号之间的联系。

这个属性是可选的,编译器可以选择不生成该属性。

下面是该属性的结构(同样给出了全局的位置关系,LineNumberTable在图的右下角部分):
由于这个属性并不是重点,我们在此简单的讲述。

每个LineNumberTable中的line_number_table部分,可以看做是一个数组,数组的每项是一个line_number_info ,每个line_number_info 结构描述了一条字节码和源码行号的对应关系。

其中start_pc是这个line_number_info 描述的字节码指令的偏移量, line_number是这个line_number_info 描述的字节码指令对应的源码中的行号。

可以看出,方法中的每条字节码都对应一个line_number_info ,这些line_number_info 中的line_number可以指向相同的行号,因为一行源码可以编译出多条字节码。

LocalVariableTable属性
LocalVariableTable 属性建立了方法中的局部变量与源代码中的局部变量之间的对应关系。

这个属性存在于Code属性中。

这个属性是可选的,编译器可以选择不生成这个属性。

该属性的结构如下:(同样给出了全局的位置关系图,LocalVariableTable 在该图的右下角)
由于这个属性相对不那么重要,这里只是大概讲解一下。

每个LocalVariableTable 的local_variable_table部分可以看做是一个数组,每个数组项是一个叫做local_variable_info 的结构,该结构描述了某个局部变量的变量名和描述符,还有和源代码的对应关系。

下面讲解local_variable_info的各个部分:
start_pc是当前local_variable_info所对应的局部变量的作用域的起始字节码偏移量;
length是当前local_variable_info所对应的局部变量的作用域的大小。

也就是从字节码偏移量start_pc 到start_pc+length就是当前局部变量的作用域范围;
name_index指向常量池中的一个CONSTANT_Utf8_info,该CONSTANT_Utf8_info描述了当前局部变量的变量名;
descriptor_index指向常量池中的一个CONSTANT_Utf8_info,该CONSTANT_Utf8_info描述了当前局部变量的描述符;
index描述了在该方法被执行时,当前局部变量在栈帧中局部变量表中的位置。

由此可知,方法中的每个局部变量都会对应一个local_variable_info 。

Exceptions属性
首先需要说明,Exceptions属性不是存在于Code属性中的,它存在于method_info中的attributes中。

和Code属性是平级的。

这个属性描述的是方法声明的可能会抛出的异常,也就是方法定义后面的throws声明的异常列表,请不要和上面提到的异常处理器混淆。

异常处理器描述了方法的字节码如何处理异常,而Exceptions属性描述方法可能会抛出哪些以异常。

下面讲解Exceptions属性的结构(左下角为Exceptions属性):
下面讲解Exceptions属性中的信息。

attribute_name_index和attribute_length就不多说了,和其他属性是一样的。

number_of_exceptions是该方法要抛出的异常的个数。

exceptions_index_table可以看做一个数组,这个数组中的每一项占两个字节,这两个字节是对常量池的索引,它指向一个常量池中的CONSTANT_Class_info。

这个CONSTANT_Class_info描述了一个被抛出的异常的类型。

总结
到此为止,和方法相关的属性就介绍完了。

这篇博客讲解的内容相对比较复杂。

下面以一个实例进行验证,实例代码:
反编译后的test方法部分(省略了常量池等信息):
结合上面的讲解和图解,再分析反编译的结果,就一目了然了:所有的结果是一个method_info, method_info开始处是访问标志信息。

然后是method_info的 Exceptions属性, Exceptions属性属性下面是Code属性,Code属性中又包括字节码,异常处理器,LineNumberTable属性和LocalVariableTable 属性。

所以会直接或间接的和method_info有联系,最后给出一张全局图,这样的话,读者就比较明确,一个完整的方法,是如何在class文件中描述的,由于考虑到复杂性,这些属性或其他数据项中,对常量池的引用均未画出:
本文作者:zhangjg。

相关文档
最新文档