一、类加载
定义
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化
加载
就是指将.class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象。
连接
验证是否有正确的内部结构,并和其他类协调一致
准备负责为类的静态成员分配内存,并设置默认初始化值
解析将类的二进制数据中的符号引用替换为直接引用
初始化就是我们以前讲过的初始化步骤
2.加载的时机
创建类的实例
访问类的静态变量,或者为静态变量赋值
调用类的静态方法
使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
加载某个类的子类
直接使用java.exe命令来运行某个主类
真正在使用这个类型的时候
二、类加载器的概述和分类
定义
负责将.class文件加载到内存中,并为之生成对应的Class对象。虽然我们不需要关心类加载机制,但是了解这个机制我们就能更好的理解程序的运行
2.类加载器的分类
BootstrapClassLoader根类加载器
ExtensionClassLoader扩展类加载器
SysetmClassLoader系统类加载器
AppClassLoader应用类加载器
3.类加载器的作用
BootstrapClassLoader根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
ExtensionClassLoader扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
SysetmClassLoader系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
AppClassLoader加载其他类
负载一些非核心类和程序猿自己写的类
4.演示
publicstaticvoidmain(String[]args){ //获取TestDemo类的类加载器 System.out.println(TestDemo.class.getClassLoader()); }
三、自定义类加载器
双亲委派模型
当前类加载器从自己已经加载的类中查询是否此类已经加载,如果已经加载则直接返回原来已经加载的类。
如果没有找到,就去委托父类加载器去加载(如代码c=parent.loadClass(name,false)所示)。父类加载器也会采用同样的策略,查看自己已经加载过的类中是否包含这个类,有就返回,没有就委托父类的父类去加载,一直到根类加载器。因为如果父加载器为空了,就代表使用根类类加载器作为父加载器去加载
如果根类类加载器加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用拓展类加载器来尝试加载,继续失败则会使用AppClassLoader来加载,继续失败则会抛出一个异常ClassNotFoundException,然后再调用当前加载器的findClass()方法进行加载
2.好处
主要是为了安全性,避免用户自己编写的类动态替换Java的一些核心类,比如String。
同时也避免了类的重复加载,因为JVM中区分不同类,不仅仅是根据类名,相同的class文件被不同的ClassLoader加载就是不同的两个类
案例演示
publicclassMyClassLoaderextendsClassLoader{ privateStringpath; publicMyClassLoader(Stringpath){ super(); this.path=path; } @Override protectedClass<?>findClass(Stringname)throwsClassNotFoundException{ //读取本地文件 byte[]bs=getBytes(path); //将字节数组装载成Class对象 Class<?>clazz=this.defineClass(name,bs,0,bs.length); returnclazz; } privatebyte[]getBytes(Stringpath){ try( FileInputStreamfis=newFileInputStream(path); ByteArrayOutputStreambos=newByteArrayOutputStream(); ){ byte[]bs=newbyte[1024]; intlen; while((len=fis.read(bs))!=-1){ bos.write(bs,0,len); } returnbos.toByteArray(); }catch(Exceptione){ } returnnull; } } publicstaticvoidmain(String[]args)throwsException{ MyClassLoaderclassLoader=newMyClassLoader("D:\Student.class"); Class<?>clazz=classLoader.findClass("com.qianfeng.Student"); //Class<?>class1=Class.forName("com.qianfeng.Student",true,classLoader); Objectobj=clazz.newInstance(); System.out.println(obj.getClass().getClassLoader()); }
四、反射
定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法
对于任意一个对象,都能够调用它的任意一个方法和属性
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
要想解剖一个类,必须先要获取到该类的字节码文件对象
而解剖使用的就是Class类中的方法,所以先要获取到每一个字节码文件对应的Class类型的对象
说白了就是获取一个类的骨架
2.获取字节码的三种方式
对象.getClass()
类名.class
Class类中静态方法forName("类名")
3.演示
publicstaticvoidmain(String[]args)throwsException{ Studentstudent=newStudent(); Class<?>clazz1=student.getClass(); Class<?>clazz2=Student.class; Class<?>clazz3=Class.forName("com.qianfeng.Student"); }
五、反射获取构造函数
定义
Class类的newInstance()方法是使用该类无参的构造函数创建对象
如果一个类没有无参的构造函数,就不能这样创建了,可以调用Class类的getConstructor(String.class,int.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三",20)方法创建对象
2.演示
publicstaticvoidmain(String[]args)throwsException{ Class<?>clazz=Class.forName("com.qianfeng.Student"); Studentobject=(Student)clazz.newInstance(); object.method(); }
以上就是动力节点Java培训机构小编介绍的“Javaweb学习视频:反射动态代理”的内容,希望对大家有帮助,如有疑问,请在线咨询,有专业老师随时为你服务。
你适合学Java吗?4大专业测评方法
代码逻辑 吸收能力 技术学习能力 综合素质
先测评确定适合在学习