java反射
一、类的加载
1.1类的加载过程
1.2类的加载器
二、反射
2.1反射的定义
java反射机制是在运行状态中,对于任意一个类,都能够知道这个类所属的属性和方法。对于任意一个对象,都能调用它任意的一个方法和属性。这种动态获取信息以及动态调用对象的方法功能称为java语言的反射机制
2.2获取Class对象
/**
* 反射:通过.class文件对象,去使用该文件中的成员变量、成员属性、成员方法
*/
public class demo1 {
public static void main(String[] args) throws ClassNotFoundException {
//获取Class对象
//方式1:Object类中的getclass
Student student = new Student("张三",18);
Class c1 = student.getClass();
//方式2:任意数据类型的静态class-----练习中使用
Class c2 = Student.class;
Student student2 = new Student("张三",18);
Class c3 = student2.getClass();
// System.out.println(c1==c2);//true
// System.out.println(student==student2);//false
// System.out.println(c1==c3);//true
//方式3:通过Class类中的静态方法,必须指定路径----------开发中常使用
Class c4 = Class.forName("org.wdit.Reflect.Student");
System.out.println(c1==c4);//true
}
}
2.3获取构造方法
/**
* 构造方法获取
*/
public class demo2 {
public static void main(String[] args) throws Exception {
Class c1 = Student.class;
//获取所有公共修饰的方法
Constructor[] constructors = c1.getConstructors();
for (Constructor con : constructors) {
System.out.println(con);
}
System.out.println("-------------------------------------------");
//获取所有的构造方法
Constructor[] declaredConstructors = c1.getDeclaredConstructors();
for (Constructor con : declaredConstructors) {
System.out.println(con);
}
System.out.println("---------------------------------------------");
//获取一个公共的构造方法
Constructor constructor = c1.getConstructor();
System.out.println("------------------------------------------");
//创建一个类对象的实例
Object object = constructor.newInstance();
System.out.println(object);
System.out.println("-------------------------------------------");
Constructor constructor1 = c1.getConstructor(String.class, int.class, String.class);
Object o = constructor1.newInstance("李四",18,"男");
System.out.println(o);
}
}
2.4获取私有方法的构造
/**
* 通过私有方法创建对象
*/
public class demo3 {
public static void main(String[] args) throws Exception {
Class c = Class.forName("org.wdit.Reflect.Student");
//获取构造方法
Constructor constructor = c.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
Object o = constructor.newInstance("lily");
System.out.println(o);
}
}
2.5获取成员变量
/**
* 获取成员变量:
*/
public class demo4 {
public static void main(String[] args) throws Exception{
Class c = Student.class;
//获取所有公共的成员变量
Field[] fields = c.getFields();
for (Field f:fields){
System.out.println(f);
}
System.out.println("-----------------------------");
//获取所有成员变量
Field[] declaredFields = c.getDeclaredFields();
for (Field f:declaredFields) {
System.out.println(f);
}
System.out.println("------------------------------");
Constructor constructor = c.getConstructor();
Object obj = constructor.newInstance();
System.out.println(obj);
//获取单个成员变量
Field sex = c.getField("sex");
Field name = c.getDeclaredField("name");
Field age = c.getDeclaredField("age");
sex.set(obj,"男");
name.setAccessible(true);
name.set(obj,"张三");
age.set(obj,18);
System.out.println(obj);
}
}
//建议日后使用中,无论什么修饰权限的,我们都使用带Declared,以及设置Accessible
2.6成员方法
/**
* 成员方法:
*/
public class demo5 {
public static void main(String[] args) throws Exception {
Class c = Class.forName("org.wdit.Reflect.Student");
//获取全部成员方法 自己以及父类
Method[] methods = c.getMethods();
for (Method m:methods) {
System.out.println(m);
}
System.out.println("---------------------------------------------");
//获取自己的成员方法
Method[] declaredMethods = c.getDeclaredMethods();
for (Method m:declaredMethods) {
System.out.println(m);
}
System.out.println("-------------------------------------------");
//获取单个成员方法并使用
Constructor constructor = c.getConstructor();
Object o = constructor.newInstance();
Method method = c.getMethod("show1");
//o.show1(); 写法错误
method.invoke(o);
System.out.println("---------------------------------------------");
Method method2 = c.getMethod("show2", String.class);
method2.invoke(o,"李四");
System.out.println("--------------------------------------------");
Method method3 = c.getMethod("show3", String.class);
Object o1 = method3.invoke(o, "哈哈");
System.out.println(o1);
System.out.println("---------------------------------------------");
Method method4 = c.getDeclaredMethod("show4");
method4.setAccessible(true);
method4.invoke(o);
}
}
2.7练习题
1:
/**
* 使用配置文件运行类中的方法
*/
public class Testdemo {
public static void main(String[] args) throws Exception {
//加载配置文件
Properties properties = new Properties();
FileReader fr = new FileReader("D:\\桌面\\java\\src\\Properties.txt");
properties.load(fr);
fr.close();
//获取数据
String ClassName = properties.getProperty("ClassName");
String MethodName = properties.getProperty("MethodName");
// 反射加载对应的类并调用方法
Class c = Class.forName(ClassName);
//创建对象
Constructor constructor = c.getConstructor();
Object o = constructor.newInstance();
//调用方法
Method method = c.getMethod(MethodName);
method.invoke(o);
}
}
2:
/**
* 给定一个指定的泛型Integer类型的ArrayList的集合,在这个集合中添加一个字符串
*/
public class Testdemo2 {
public static void main(String[] args) throws Exception {
ArrayList<Integer> arrayList = new ArrayList<>();
//获取对应的字节码文件
Class c = arrayList.getClass();
//获取方法
Method method = c.getMethod("add", Object.class);
//使用方法
method.setAccessible(true);
method.invoke(arrayList,"hello");
System.out.println(arrayList);
}
}
3:
写一个方法,此方法可以给 指定对象的属性赋值
public class Testdemo3 {
public static void main(String[] args) throws Exception {
Dog dog =new Dog();
System.out.println(dog);
Tool tool = new Tool();
tool.setProperty(dog,"name","博美");
tool.setProperty(dog,"age",10);
System.out.println(dog);
}
}
------------------------------------------------------
class Dog{
private String name;
int age;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
------------------------------------------------------
class Tool{
public void setProperty(Object obj,String filedName,Object value) throws Exception {
//先拿到指定对象的字节码文件
Class c= obj.getClass();
//获取属性名
Field field = c.getDeclaredField(filedName);
//抑制访问权限
field.setAccessible(true);
field.set(obj,value);
}
}
三、动态代理
3.1概述:
代理就是原本自己做的事情,请了别人帮你完成,被请的人就是代理对象
即是在程序运行过程中产生的对象-----通过反射产生代理
3.2动态代理应用
/*
* Proxy:提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
* public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
* 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序。
*
* InvocationHandler:由代理实例的调用处理程序实现的接口。
* invoke(Object proxy, 方法 method, Object[] args) 处理代理实例上的方法调用并返回结果。
*/
public class ProxyDemo {
public static void main(String[] args) {
UserDao userDao = new UserDaoImpl();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(userDao);
//创建代理对象
UserDao proxy = (UserDao)Proxy.newProxyInstance(userDao.getClass().getClassLoader(),userDao.getClass().getInterfaces(),
myInvocationHandler);
proxy.add();
proxy.del();
}
}
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("权限校验");
Object result = method.invoke(object,args);//代理对象
System.out.println("日志记录");
return result;
}
}
public interface UserDao {
public abstract void add();
public abstract void del();
}
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("添加");
}
@Override
public void del() {
System.out.println("删除");
}
}
ic abstract void del();
}
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("添加");
}
@Override
public void del() {
System.out.println("删除");
}
}