1:反射
(1)类的加载及类加载器
当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。
加载
就是指将class文件读入内存,并为之创建一个Class对象。
任何类被使用时系统都会建立一个Class对象。
连接
验证 是否有正确的内部结构,并和其他类协调一致
准备 负责为类的静态成员分配内存,并设置默认初始化值
解析 将类的二进制数据中的符号引用替换为直接引用
初始化 就是我们以前讲过的初始化步骤
类加载器
负责将.class文件加载到内存中,并为之生成对应的Class对象。
类加载器的组成
Bootstrap ClassLoader 根类加载器,也被称为引导类加载器,负责Java核心类的加载
Extension ClassLoader 扩展类加载器,负责JRE的扩展目录中jar包的加载。
Sysetm ClassLoader 系统类加载器,负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径
反射:
通过字节码文件对象,去使用成员变量,构造方法,成员方法
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
获取构造方法
getConstructors
getDeclaredConstructors
创建对象
newInstance() 创建此 Class 对象所表示的类的一个新实例。
con.newInstance(“zhangsan", 20);
获取所有成员
getFields,getDeclaredFields
获取单个成员
getField,getDeclaredField
修改成员的值
set(Object obj,Object value)???将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
获取所有方法
getMethods
getDeclaredMethods
获取单个方法
getMethod
getDeclaredMethod
暴力访问
method.setAccessible(true);
Object invoke(Object proxy,
Method method,
Object[] args)
throws Throwable在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。
(3)反射的使用
A:通过反射获取构造方法并使用
B:通过反射获取成员变量并使用
C:通过反射获取成员方法并使用
/*1、 ArrayList<Integer> list = new ArrayList<Integer>(); 在这个泛型为Integer的ArrayList中存放一个String类型的对象。
* */
package com.itheima;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Test1 {
public static void main(String[] args) throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
NoSuchMethodException, SecurityException {
ArrayList<Integer> list = new ArrayList<Integer>();
Class c = list.getClass();// 集合ArrayList的class文件对象
Method m = c.getMethod("add", Object.class);
m.invoke(list, "qwe");// 调用list的add方法,传入值一个字符串对象
System.out.println(list);
}
}
(4)反射案例
A:通过反射运行配置文件的内容
B:通过反射越过泛型检查
C:通过反射给任意的一个对象的任意的属性赋值为指定的值
(5)动态代理:其实就是通过反射来产生一个代理。
在Java中java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口就可以生成动态代理对象。JDK提供的代理只能针对接口做代理。我们有更强大的代理cglib
案例
//创建接口
public interface UserDao {
public abstract void add();
public abstract void delete();
public abstract void update();
public abstract void find();
}
//创建类实现接口
public class UserDaoImpl implements UserDao{
@Override
public void add() {
System.out.println("添加功能");
}
@Override
public void delete() {
System.out.println("删除功能");
}
@Override
public void update() {
System.out.println("更新功能");
}
@Override
public void find() {
System.out.println("查找功能");
}
}
//创建类实现InvocationHandler接口,重写invoke()方法
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("权限校验");
Object result=method.invoke(target, args);
System.out.println("日志记录");
return result;
}
}
public class InvocationTest {
public static void main(String[] args) {
//创建目标对象
UserDao ud=new UserDaoImpl();
//对ud对象做一个代理对象
MyInvocationHandler handler=new MyInvocationHandler(ud);
UserDao proxy=(UserDao) Proxy.newProxyInstance(ud.getClass().getClassLoader(), ud.getClass().getInterfaces(), handler);
proxy.add();
proxy.delete();
proxy.find();
proxy.update();
}
}
案列:通过配置文件运行类中的方法
package cn.itcast.heima;
public class DemoClass {
public void run()
{
System.out.println("welcome to heima!");
}
}
配置文件(知道有那几个键)
className=cn.itcast.heima.DemoClass
methodName= run
程序:
ackage com.itheima;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/*Properties格式的配置文件在JRE系统库下*/
public class Test7 {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
//加载键值对数据
Properties prop=new Properties();
FileReader fr=new FileReader("Test7.txt");
prop.load(fr);
fr.close();
//获取数据
String className=prop.getProperty("className");
String methodName=prop.getProperty("methodName");
//反射
Class c=Class.forName(className);
Constructor con=c.getConstructor();
Object obj=con.newInstance();
Method m=c.getMethod(methodName);
m.invoke(obj);
}
}
|
|