类加载机制以及Java-Reflect(反射)

本文详细介绍了Java类的加载过程,包括加载、验证、准备、解析、初始化、使用和卸载七个阶段,以及JVM内存的划分。重点讲解了反射机制,包括Class类、Constructor类、Field类和Method类的使用,以及反射在动态创建对象和编译中的灵活性。此外,还讨论了类的静态和非静态内容初始化的时机以及类的卸载与GC的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类加载过程

1、类的生命周期

指的是一个类被加载到JVM中运行到被卸载的过程,类的生命周期主要经过了类加载,验证,准备,解析,初始化,使用和卸载7个步骤。

2、类加载

主要是把class文件加载到JVM中,同时生成该类所对应的Class对象,该class对象是Java反射的起源,通过该对象可以在类运行期间‘窥探’类的结构信息。


3、类的连接

   (1)验证:JVM负责检查被加载的类是否有正确的内部结构

   (2)准备:负责为类变量分配内存

   (3)解析:将类在编译期间的符号引用转换为直接引用

com.imooc.reflect.Foo@15db9742


4、类的初始化:JVM负责对类的静态内容进行初始化,而非静态内容则是等到实例化阶段才初始化。

5、类的使用:类在JVM 中被使用,例如:实例化对象,读取和设置变量等信息

6、类的卸载:主要是使用GC对实例进行回收,在方法区清空类的信息等

 

二、JVM将内存划分区域:


1、栈内存:主要用来存储局部变量,对象的引用,方法的入口等信息

2、堆内存:主要用来存储通过new运算符创建的对象

3、方法区:主要用来存储类的结构信息,静态变量等内容

4、本地方法栈:用来在底层调用非Java语言编写的应用程序。

5、程序计数器:用来存储线程的指令地址




类加载器(ClassLoader)负责将.class文件加载到内存中,并为之生成对应的Java.lang.Class对象,此外,其加载机制为“非一次性加载,而是在需要的时候加载”

在JVM中,类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载7个阶段


在java中,一个java类将会编译成一个class文件。在编译时,java类并不知道引用类的实际内存地址,因此只能使用符号引用来代替。比如org.simple.People类引用org.simple.Tool类,在编译时People类并不知道Tool类的实际内存地址,因此只能使用符号org.simple.Tool(假设)来表示Tool类的地址。而在类装载器装载People类时,此时可以通过虚拟机获取Tool类 的实际内存地址,因此便可以既将符号org.simple.Tool替换为Tool类的实际内存地址,及直接引用地址


反射机制指的是程序在运行时能够获取类的信息。在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。

反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中,在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象。



三、反射

1、反射是什么

能够分析类能力的程序成为“反射”

2、反射机制作用

--在运行时分析类的能力
--在运行时查看类的对象(eg:编写一个toString方法供所有类使用)
--实现通用的数组操作代码
--利用Method对象

四、关于反射

一、Class类--可获取类和类的成员信息


在面向对象的世界,万事万物皆对象

类是对象,类是java.lang.Class类的实例对象

There is a classnamed Class

 

在Java中每个类被加载之后,系统就会为该类生成一个对应的

Class对象,通过该Class对象就可以访问到JVM中的这个类了,继而

获取该类的相关信息。在Java程序中获得 Class 对象有如下三种方式:

 

1、 使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(即必须添加完整包名和类名)


Class c1 =Class.forName("com.ysit.reflect.Demo");

Class.forName(“类的全称”)

A、不仅表示了类的类类型,还代表了动态加载类

B、区分编译、运行

C、编译时刻加载类是静态加载类

运行时刻加载类是动态加载类

  *new创建对象 是静态加载类,在编译时刻就需要加载所有的可能使用到的类。

  *通过Class.forName(动态加载类),在运行时刻加载

 

2、 调用某个类的class属性来获取该类对应的Class对象。例如:person.class将会返回person类对应的Class对象。

 

//实际在告诉我们任何一个类都有一个隐含的静态成员变量class

       Class c2 = Demo.class;

 

3、 调用某个对象的getClass()方法。该方法是Object类的一个方法,所以所有的Java对象都可以调用该方法,该方法将会返回该对象所属类对应的class对象。

Eg:

    Demodemo = new Demo();

    //已经知道该类的对象通过grtClass方法

    Classc3 = demo.getClass();

 

System.out.println(c2== c3);  //true

System.out.println(c1== c2);  //true


二、Constructor类—可调用类的构造方法






// Class的newInstance()方法是实现"虚拟构造器"的一种途径
//虚拟构造器允许你声明:我不知道你的确切类型,但是无论如何要正确地创建你自己
//使用newInstance()来创建的类,必须带有默认的构造器






如果类中有有参构造,那么利用反射进行实例化对象时需要以下步骤:


1、  访问该类的有参构造,同时传入该有参构造类型对应的Class对象

2、  调用Constructor对象的newInstance()方法




三、Field类—可访问类的属性  






四、Method类—可调用类的方法 





五、注意:反射的操作都是编译之后的操作


Java中集合的泛型,是防止错误输入的,只在编译阶段有效,绕过编译就无效了
验证: 通过反射的反射绕过编译来证明



总结一下:





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值