类加载机制与反射知识点

本文探讨Java反射的核心概念,包括类的加载、连接和初始化过程,类加载器的运作,如何查看和获取类信息,以及利用反射创建对象和JDK动态代理。讲解了Class对象的使用、构造器和方法调用,以及动态代理在AOP中的应用。
摘要由CSDN通过智能技术生成

一、类的加载、连接、初始化

1、类----->动态获取对象、运行时信息、创建Java对象、调用Java方法、访问并修改成员变量值

2、一个JVM的所有线程、所有变量都在同一个进程中,使用该JVM的进程的内存

两个JVM不会共享数据

3、加载类的二进制数据来源:

(1)本地文件系统加载class文件

(2)JAR包 eg.数据库驱动类

(3)通过网络加载class文件

(4)Java源文件动态编译并加载

4、类连接:把类的二进制数据合并到JRE

5、创建实例:new、反射、反序列化

6、final型的类变量如果在编译时可以确定下来,类变量相当于宏变量

7、Class Loader的loadClass()加载类,Class的forName()静态方法强制初始化类

二、类加载器

1、类加载器:将.class文件加载到内存中,生成对应的java.lang.Class对象,

一旦类被载入JVM中,同一个类就不会被再次载入了

使用类的全限定类名唯一标识

根类加载器 BootStrap扩展类加载器 Extension系统类加载器 Sysytem
类加载器是由JVM自身实现的负责加载JRE的扩展目录负责JVM启动时加载java命令
不由Java实现的其父类加载器是根类加载器getSystemClassLoader(),加载路径是程序运行的当前路径

2、类加载机制:全盘负责、父类委托、缓存机制

缓存机制:所有加载过的Class都会被缓存,因此修改了Class之后,必须重启JVM,程序修改才会生效

3、自定义类加载器:继承ClassLoader

4、URLClassLoader:可以从本地/远程主机获取二进制文件来加载类

eg.加载MySQL驱动,获取数据库连接

//URLClassLoader
URLClassLoader urlClassLoader = new URLClassLoader(urls);
//Driver
Driver driver = (Driver) urlClassLoader.loadClass("com.mysql.jdbc.Driver").newInstance();

三、发射查看类信息

1、编译时类型:instanceof强制类型转换;运行时类型:反射

2、类被加载后,生成对应Class对象,获取Class对象的3种方法:

Class的forName静态方法类的class属性对象的getClass()方法
Class clazz = Class.forName(A)Class clazz = A.class;Class clazz = a.getClass();
参数是全限定类名

3、从Class类中获取信息:构造器、方法、成员变量、内部类、注解等

构造器方法成员变量
getConstructor(Class[]getMethod(String name,Class[] params)getField(String name)
getConsturctors()getMethods()getFields()
getDeclaredConstructor()getDeclaredMethod(String name,Class[] params)getDeclaredFieldString name)
getDeclaredConsturctors():getDeclaredMethods()getDeclaredFields()
Annotation内部类修饰符、所在包、类名接口、枚举、注解
getAnnotation(Class annotationClass)getDeclaredClasses()getModifiers()isAnnotation()
getDeclaredAnnotations()getDeclaringClass()getPackage()isAnnotationPresent()
getAnnotationByType(Class annotationClass)getInterfaces()getName()isAnonymousClass()
getDeclaredAnnotationByType(Class annotationClass)getSuperClass()getSimpleName()

4、对于只能在源代码上保留的注解,使用获得的Class对象无法访问到该注解对象 @Retention(Value=SOURCE)

5、javac命令编译Java源文件时,默认生成的class文件不包含方法得形参名信息

四、利用反射生成对象

1、反射生成对象的两种方式:

(1)用Class对象的newInstance()创建类的实例,要求Class对象含有默认构造器 (常见)

根据配置文件信息创建Java对象使用(1)方法,通过配置文件读取类名,利用反射创建对象

(2)先用Class对象获取Constructor对象,再调用Constructor的newInstance()方法创建类的实例

//(1)
Class<T> clazz = Class.forName(clazzName);
clazz.newinstance();

//(2)
Class<T> clazz = Class.forName("...");
Constructor constructor = clazz.getConstructor(String.class);
Object obj = constructor.newInstance("..");

2、Class对象的getMethods()获取方法,Method中含有invoke()方法,用于调用指定方法

可以先调用Method的setAccessible(boolean flag),指定是否使用访问权限检查,true取消权限检查,从而实现利用反射调用private方法

3、getDeclaredField()可以获取所有方法,getField()只能获取public方法

五、利用反射生成JDK动态代理

1、通过使用java.lang.reflect包下的Proxy类和InvocationHandler接口,生成JDK动态代理类或动态代理对象

2、Proxy:用于创建动态代理类和代理对象的静态方法,即所有动态代理类的父类

Proxy创建动态代理实例的两种方式:

(1)static Class getProxyClass(ClassLoader loader, Class…interfaces)

ClassLoader :指定生成动态代理类的类加载器

interfaces:代理类将实现interfaces指定的接口

(2)static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

直接创建动态代理对象,实现interfaces指定接口,执行代理对象的每个方法时会被替换执行InvocationHandler对象的invoke()方法

//常用(2)
InvocationHandler handler = new MyInvocationHandler();
Person p  = (Foo) Proxy.newInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handler);

/** 
* 执行动态代理对象的所有方法都会执行invoke方法
* proxy:动态代理对象
* method:正在执行的方法
* args:调用目标方法是传入的参数
*/
public Object invoke(Object proxy, Method method, Object[] args) {
    ...
}

2、JDK动态代理只能为接口创建动态代理,动态代理可以实现解耦,通常生成动态代理时都是为指定目标对象生成动态代理,这种动态代理在AOP中称为AOP代理

3、在反射中使用泛型,可以避免反射生成的对象进行强制类型转换

(参考Java疯狂讲义)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值