目录
1、什么是反射?
反射允许对封装类的字段、方法和构造函数(构造方法)进行编码访问。
2、获取Class对象的三种方式
(1)Class.forName("全类名");
/**
* Class.forName();
* 最常用的一种方式
*/
try{
Class clz1 = Class.forName("com.entity.Student");
System.out.println(clz1);
}catch(ClassNotFoundException e){
e.printStackTrace();
}
//运行结果: class com.entity.Student
(2)类名.class
/**
* 类名.class
* 一般是当作参数进行传递
*/
Class clz2 = Student.class;
System.out.println(clz2);
//运行结果:class com.entity.Student
(3)对象.getClass
/**
* 当我们已经有这了类的对象时,才可以使用
*/
Student stu = new Studnet();
Class clz3 = stu.getClass();
System.out.println(clz3);
//运行结果:class com.entity.Student
3、反射获取构造方法
Constructor<?>[] getConstructors() | 返回所有公共构造方法对象的数组 |
Constructor<?>[] getDeclaredConstructors() | 返回所有构造方法对象的数组 |
Constructor<T>[] getConstructor(Class<?>... parameterTypes) | 返回单个公共构造方法 |
Constructor<T> getConstructor(Class<?>... paramterTypes) | 返回单个构造方法对象(包括私有的) |
/**
* 利用反射获取构造方法
*/
public class ReflectConstructors {
// 一般不在main方法声明异常,现为演示声明异常使得代码可读性更好
public static void main(String[] args) throws Exception {
//1、获取字节码对象
Class clz = Class.forName("com.entity.Student");
System.out.println("==== 返回所有“公共”构造方法对象的数组 =====");
Constructor[] con1 = clz.getConstructors();
for (Constructor allCon1 : con1
) {
System.out.println(allCon1);
}
System.out.println("==== 返回所有构造方法对象的数组 =====");
Constructor[] delCon1 = clz.getDeclaredConstructors();
for (Constructor allDel : delCon1
) {
System.out.println(allDel);
}
System.out.println("==== 返回单个“公共”无参构造方法 =====");
Constructor con2 = clz.getConstructor();
System.out.println(con2);
System.out.println("==== 返回单个“公共”有参构造方法 =====");
Constructor con3 = clz.getConstructor(String.class);
//多个参数 : Constructor con3 = clz.getConstructor(String.class, Integer.class);
System.out.println(con3);
System.out.println("==== 返回单个有参参构造方法(包括私有) =====");
Constructor del2 = clz.getDeclaredConstructor(String.class,String.class,Integer.class);
System.out.println(del2);
}
}
T newInstance(Object... initargs) | 根据指定的构造方式创建对象 |
setAccessible(boolean flag) | 设置为 true,表示取消访问检查 |
System.out.println("== newInstance ===");
// 获取私有构造方法
Constructor c = clz.getConstructor(String.class, Integer.class);
// 去除权限控制
c.setAccessible(true);
//创建对象
Student stu2 = (Student) c.newInstance("小王", 12);
System.out.println(stu2.getName() + stu2.getAge());
4、反射获取成员变量
Field[] getFields() | 返回所有公共变量对象的数组 |
Field[] getDecaredFieds() | 返回所有成员变量对象的数组 |
Field getField(String name) | 返回单个公共成员变量对象 |
Field getDeclaredField(String name) | 返回单个成员变量对象 |
/**
* 反射获取成员变量
*/
public class ReflectMember {
public static void main(String[] args) throws Exception {
// 1、创建字节码对象
Class clz = Class.forName("com.entity.Student");
System.out.println("=== 返回所有“公共”变量对象的数组 ===");
Field[] allFie1 = clz.getFields();
for (Field stu : allFie1
) {
System.out.println(stu);
}
System.out.println("=== 返回所有变量对象的数组 ===");
Field[] allFie2 = clz.getDeclaredFields();
for (Field fie2 : allFie2
) {
System.out.println(fie2);
}
System.out.println("=== 返回单个“公共”变量对象 ===");
Field name1 = clz.getField("like");
System.out.println(name1);
System.out.println("=== 返回单个变量对象 ===");
Field name2 = clz.getDeclaredField("name");
System.out.println(name2);
}
}
void set(Object obj,Object value) | 赋值 |
Object get(Object obj) | 获取值 |
System.out.println("=== 获取成员变量记录的值===");
Student stu = new Student("zhangsan", 12);
Field getName2 = clz.getDeclaredField("name");
//关闭权限检查
getName2.setAccessible(true);
String value = (String) getName2.get(stu);
System.out.println(value);
System.out.println("=== 修改对象里面记录的值 ===");
getName2.set(stu, "wangwu");
System.out.println(stu.getName());
5、反射获取成员方法
Method[] getMethods | 返回所有公共成员方法对象的数组,包括继承的 |
Method[] getDeclaredMethods() | 返回所有成员方法对象的数组,不包括继承的 |
Method getMethod(String name ,Class<?> parameterTypes) | 返回单个公共成员方法对象 |
Method getDeclaredMethod(String name,Class<?>... parameterTypes) | 返回单个成员方法的对象 |
/**
* 利用反射获取成员方法
*/
public class ReflectMethod {
public static void main(String[] args) throws Exception {
// 创建字节码对象
Class clz = Class.forName("com.entity.Student");
System.out.println(" === 返回所用“公共”成员方法对象的数组,包括继承的 ====");
Method[] met1 = clz.getMethods();
for (Method met : met1
) {
System.out.println(met);
}
System.out.println(" === 返回所用成员方法对象的数组,不包括继承的 ====");
Method[] del1 = clz.getDeclaredMethods();
for (Method del : del1
) {
System.out.println(del);
}
System.out.println(" === 返回单个“公共”成员方法对象 ====");
Method study = clz.getMethod("study");
System.out.println(study);
System.out.println(" === 返回单个成员方法对象 ====");
Method show = clz.getDeclaredMethod("show");
System.out.println(show);
System.out.println(" === 获取方法的权限修饰符 ====");
int modShow = show.getModifiers();
// 1:公开 2:私有 3:受保护的
System.out.println(modShow);
System.out.println(" === 获取方法抛出的异常 ====");
Class[] exceptionTypes = show.getExceptionTypes();
for (Class ex : exceptionTypes
) {
System.out.println(ex);
}
System.out.println("=== 获取方法的形参 ===");
Class[] exceptionTypes1 = show.getExceptionTypes();
for (Class types : exceptionTypes1
) {
System.out.println(types);
}
System.out.println("=== 获取方法并运行 ===");
Student student = new Student();
Method test = clz.getDeclaredMethod("test");
Object stu = test.invoke(student);
System.out.println("获取方法的返回值" + stu);
}
}
Method类中用于创建对象的方法
Object invoke(Object obj,Object... args); 运行方法
参数一:用obj对象调用该方法;
参数二:调用方法传递的参数(没有就不写)
返回值:方法的返回值(没有就不写)
6、反射的作用
(1)获取一个类里面的所有信息,获取到之后再执行其他的业务逻辑操作
(2)可结合配置文件,动态的创建对象并调用方法
public static void main(String[] args) throws Exception {
//1、读取配置文件中的信息
Properties pos = new Properties();
FileInputStream fis = new FileInputStream("C:\\Users\\lenovo\\IdeaProjects\\Java-Reflect\\prop.properties");
pos.load(fis);
fis.close();
System.out.println(pos);
//2、获取全类名和方法名
String classname = (String) pos.get("classname");
String method = (String) pos.get("method");
System.out.println(classname);
System.out.println(method);
//3、利用反射创建对象并运行方法
Class clz = Class.forName(classname);
// 4、构造方法
Constructor con = clz.getDeclaredConstructor();
con.setAccessible(true);
Object o = con.newInstance();
System.out.println(o);
//5、获取成员方法并运行
Method declaredMethod = clz.getDeclaredMethod(method);
declaredMethod.setAccessible(true);
declaredMethod.invoke(o);
}