目录
一,什么是反射
(1)反射java语言中的一种机制,通过这种机制可以动态的实例化对象,写属性,调用方法
(2)补充:框架:反射+设计模式组合而成的一个半成品(以下用制火药举例)
半成品就是 合成后的火药
反射+设计模式:合成后的火药
二,类类
Class.forName(完整类名)
<代码演示>
Class cls3 = Class.forName("com.dengxiyan.reflect.Student");
类名.class
<代码演示>
Class cls = Student.class;
对象.getClass
<代码演示>
Student stu = new Student();
Class cls2 = stu.getClass();
《效果图》
三,反射实例化
(1)getConstructor
(2)getDeclaredConstructor
(3)newInstance
<代码演示>
package com.dengxiyan.reflect;
import java.lang.reflect.Constructor;
/**
* 反射实例化
* 有以下几种情况
* 1.无参数 共有的构造方法
* 2.有参数 共有的构造方法
* 3.有多个参数 共有的构造方法
* 4.私有的构造方法
* @author DXY
*2022年6月16日下午2:53:09
*/
public class Demo2 {
public static void main(String[] args) throws Exception, IllegalAccessException {
//调用无参的构造方法
Student stu1 = new Student();
//调用有参的构造方法
Student stu2 = new Student("s001");
//调用有多个参数的构造方法
Student stu3 = new Student("s001","张三");
System.out.println("--------------------------以下为反射的方式实例化对象-------------------------");
//获取类类
Class<? extends Student> cls1 = stu1.getClass();
//1.无参数 共有的构造方法
System.out.println("--------------------------1.无参数 共有的构造方法-------------------------");
Student stu4 = cls1.newInstance();
/**
* 2.有参数 共有的构造方法
* (1)拿到构造器对象
*/
//(1)拿到构造器对象 三点代表乐意传多个参数 此处拿到的是一个String的构造器对象
Constructor<? extends Student> c1 = cls1.getConstructor(String.class);
System.out.println("--------------------------2.有参数 共有的构造方法-------------------------");
Student stu5 = c1.newInstance("s001");
//3.有多个参数 共有的构造方法 拿到两个参数的构造对象
Constructor<? extends Student> c2 = cls1.getConstructor(String.class,String.class);
System.out.println("--------------------------3.有多个参数 共有的构造方法-------------------------");
Student stu6 = c2.newInstance("s001","李四");
//4.私有的构造方法
//getConstructor 只能够获取共有的构造方法 ,要获取私有的构造器就需调用getDeclaredConstructor
Constructor<? extends Student> c3 = cls1.getDeclaredConstructor(Integer.class);
//打开访问权限
System.out.println("--------------------------4.私有的构造方法-------------------------");
c3.setAccessible(true);
Student stu7 = c3.newInstance(18);
}
}
《代码效果图如下》
补充: (1)拿到构造器对象 三点代表乐意传多个参数
(2) 以下标记代码默认就是调用无参 公有的 构造函数
<默认效果图如下>
《异常处理》
异常原因:getConstructor 只能够获取共有的构造方法 ,要获取私有的构造器就需调用getDeclaredConstructor
此处为什么还会抛异常 Class com.dengxiyan.reflect.Demo2 can not access a member of class com.dengxiyan.reflect.Student with modifiers "private"因为还没打开私有化访问权限
四,反射动态方法调用
(1)getMethod
(2)getDeclaredMethod
<代码演示>
package com.dengxiyan.reflect;
import java.lang.reflect.Method;
/**
* 反射动态调用方法
* 四种
* 1.调用无参的共有方法
* 2.调用1个有参的共有方法
* 3.调用私有的方法
* @author DXY
*2022年6月16日下午3:36:05
*/
public class Demo3 {
public static void main(String[] args) throws Exception{
/**
* 步骤:
* 1.先拿到类类
* 2.拿到方法对象
* 3.调用对应的方法
*/
Class<Student> cls = Student.class;
/**
* 1.调用无参的共有方法
*/
System.out.println("--------------------------1.调用无参的共有方法-------------------------");
//name:被实例的方法名 parameterTypes:值得是方法对应的参数
Method m1 = cls.getMethod("hello");
//调用对应的方法
//第一个参数:指的是类实例 第二个参数:方法调用时的实参
//m1.invoke方法调用的返回值就是方法对象本身的返回值
Object invoke = m1.invoke(cls.newInstance());
System.out.println(invoke);
/**
* 2.调用1个有参的共有方法
*/
System.out.println("--------------------------2.调用1个有参的共有方法-------------------------");
Method m2 = cls.getMethod("hello", String.class);
Object invoke2 = m2.invoke(cls.newInstance(), "张三");
System.out.println(invoke2);
/**
* 3.调用私有的方法
*/
System.out.println("--------------------------2.调用1个有参的共有方法-------------------------");
Method m3 = cls.getDeclaredMethod("add", Integer.class,Integer.class);
//打开访问权限
m3.setAccessible(true);
Object invoke3 = m3.invoke(cls.newInstance(), 5,5);
System.out.println(invoke3);
}
}
《效果图》
分析效果图:
因为此方法返回类型是void,所以为空
为什么为null,因为hello方法是无返回型的
五,反射读写属性
(1)getDeclaredField
(2)getDeclaredFields
《代码演示》
错误代码分析:
System.out.println("age: "+stu.age);
System.out.println("sname: "+stu.getSname());
System.out.println("sid: "+stu.getSid());
以上代码存在的问题
1.事先得知这个类的每个属性(对未知的东西没办法获取)
2.假设Student有30个属性呢(代码量大)
package com.dengxiyan.reflect;
import java.lang.reflect.Field;
/**
* 反射读写属性
* @author DXY
*2022年6月16日下午4:04:19
*/
public class Demo4 {
public static void main(String[] args) throws Exception {
//创建学生实例
Student stu = new Student("s003","张三");
stu.age = 20;
//需求;拿到这个学生所有的学生及属性值
//注意:一切反射从类类开始
Class<? extends Student> cls = stu.getClass();
//当前类的所有属性
Field[] fields = cls.getDeclaredFields();
System.out.println(fields.length);
//f代表每一个属性对象
for (Field f : fields) {
//打开访问权限
f.setAccessible(true);
//通过属性对象拿到属性名称
System.out.println(f.getName());
//拿到当前属性对象的属性值
System.out.println(f.get(stu));
}
}
}
《效果图》