参考代码:https://github.com/ZhangXiaoixiang/reflectdemo
springboot版本的(找java-base分支)https://gitee.com/zhang-xiao-xiang/all-demo-parent.git
说明:收集的网上资料,自己整理收集
视频教程(腾讯课堂): https://ke.qq.com/webcourse/index.html#cid=298879&term_id=100354189&taid=2094161629319039&vid=t1426y3hmoz
视频教程(网易云课堂): https://study.163.com/course/courseLearn.htm?courseId=1005927016#/learn/video?lessonId=1053358058&courseId=1005927016
1:通过反射获取类
package com.example.java.base.reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* ReflectDemo01:反射获取类相关(基本操作)
*
* @author zhangxiaoxiang
* @date 2020/11/3
*/
public class ReflectTest {
/**
* 通过反射获取类(获取反射对象的3种方式 意区别,有的需要抛异常有的不需要)
*/
public static void demo01() {
try {
Class<?> perClazz = Class.forName("com.example.java.base.reflect.Person");
System.out.println("方式1===>通过Class.forName(\"全类名\")\t" + perClazz);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Class<?> perClazz2 = Person.class;
System.out.println("方式2===>类名.class\t" + perClazz2);
Person per = new Person();
Class<?> perClazz3 = per.getClass();
System.out.println("方式3===>对象.getClass()\t" + perClazz3);
}
/**
* 为了方便,这里定义一个方法获取反射,方便后面测试,这里使用的方式一为示例
*
* @return 获取到的反射对象
*/
public static Class<?> getClassTest() {
//Class入口
Class<?> perClazz = null;
try {
perClazz = Class.forName("com.example.java.base.reflect.Person");
return perClazz;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取方法(所有的都可以)
*/
public static void demo02() throws IllegalAccessException, InstantiationException {
//Class入口
Class<?> perClazz = getClassTest();
//获取所有的 公共的方法(1.本类 以及 父类、接口中的所有方法 2.符合访问修饰符规律),注意空指针
System.out.println("===================================获取方法(所有的都可以)===========================");
Method[] methods = Objects.requireNonNull(perClazz).getMethods();
System.out.println("公共的方法==========");
for (Method method : methods) {
System.out.println(method);
}
System.out.println("所有的方法==========");
//获取当前类的所有方法(1.只能是当前类 2.忽略访问修饰符限制)
Method[] declaredMethods = perClazz.getDeclaredMethods();
for (Method declaredMethod : declaredMethods) {
System.out.println(declaredMethod);
}
System.out.println("===================================获取所有的接口===========================");
Class<?>[] interfaces = perClazz.getInterfaces();
for (Class<?> inter : interfaces) {
System.out.println(inter);
}
System.out.println("===================================获取所有的父类===========================");
Class<?> superclass = perClazz.getSuperclass();
System.out.println(superclass);
System.out.println("===================================获取所有的构造方法===========================");
Constructor<?>[] constructors = perClazz.getConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("===================================获取所有的构造方法===========================");
for (Constructor<?> constructor : constructors) {
System.out.println(constructor);
}
System.out.println("===================================获取所有的属性(公共和私有等)===========================");
System.out.println("所有公共属性====");
Field[] fields = perClazz.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("所有属性 (属性的 :公共属性 所有属性的区别 同“方法”)====");
Field[] declaredFields = perClazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
System.out.println(declaredField);
}
System.out.println("============================获取当前反射所代表类(接口) 的对象(实例)===========================");
Object instance = perClazz.newInstance();
Person per = (Person) instance;
per.interface2Method();
}
/**
* 测试
*
* @throws InstantiationException 异常1
* @throws IllegalAccessException 异常2
*/
@Test
public void test2() throws InstantiationException, IllegalAccessException {
System.out.println("************************获取反射对象的3种方式************************");
demo01();
System.out.println("************************获取反射其他信息********************************");
demo02();
}
}
2获取到反射类实例后操作
package com.example.java.base.reflect;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Properties;
/**
* ReflectDemo02:反射获取类的实例,并操作
*
* @author zhangxiaoxiang
* @date 2020/11/3
*/
public class Reflect2Test {
/**
* 为了方便,这里定义一个方法获取反射,方便后面测试,这里使用的方式一为示例
*
* @return 获取到的反射对象
*/
public static Class<?> getClassTest() {
Class<?> perClazz = null;
try {
perClazz = Class.forName("com.example.java.base.reflect.Person");
return perClazz;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* 获取对象的实例,并操作对象
*
* @throws InstantiationException
* @throws IllegalAccessException
*/
public static void demo01() throws IllegalAccessException, InstantiationException, NoSuchFieldException,
NoSuchMethodException, InvocationTargetException, IOException {
Class<?> perClazz = getClassTest();
Person per = (Person) Objects.requireNonNull(perClazz).newInstance();
per.setId(1);
per.setName("zs");
per.setAge(23);
per.setDesc("我是描述属性");
System.out.println("===============================为对象赋值============================================");
System.out.println(per.toString());
System.out.println("===============================操作属性============================================");
Field idField = perClazz.getDeclaredField("id");
//访问的是private修饰的id,但是private是私有
//修改属性的访问权限 使用反射时,如果 因为访问修饰符限制造成异常,可以通过 Field/Method/Constructor.setAccessible(true)
idField.setAccessible(true);
//per.setId(1);
idField.set(per, 2);
System.out.println("修改私有属性后:"+per.toString());
Method method = perClazz.getDeclaredMethod("privateMethodTest", null);
method.setAccessible(true);
//方法的调用:invoke()
method.invoke(per, null);
//per.say(xxx);
Method method2 = perClazz.getDeclaredMethod("privateMethodTest", String.class);
method2.setAccessible(true);
method2.invoke(per, "我是pram");
System.out.println("===============================操作构造方法============================================");
// Constructor<?>[] constructors = perClazz.getConstructors() ;//公共
// for(Constructor constructor:constructors) {
// System.out.println(constructor);
// }
// Constructor<?>[] constructors = perClazz.getDeclaredConstructors() ;//本类
// for(Constructor constructor:constructors) {
// System.out.println(constructor);
// }
//获取指定的构造方法
//在反射中,根据类型 获取方法时:基本类型(int、char...)和包装类(Integer,Character)是不同的类型
// Constructor<?> constructor = perClazz.getConstructor(Integer.class);
Constructor<?> constructor = perClazz.getConstructor(int.class);
System.out.println("获取指定的构造方法===>"+constructor);
Constructor<?> constructor2 = perClazz.getDeclaredConstructor(String.class);
System.out.println("获取指定的构造方法===>"+constructor2);
//Person per = new Person() ;
//根据获取的private构造方法,获取对象实例
constructor2.setAccessible(true);
Person per3 = (Person) constructor2.newInstance("zs");
System.out.println("获取带有String的构造方法" + per3);
//因为constructor是 有参构造方法(Integer还是int这里构造的就是什么值)
Person instance2 = (Person) constructor.newInstance(23);
System.out.println("获取带有Integer的构造方法" +instance2);
Constructor<?> constructor3 = perClazz.getConstructor();
//因为constructor3是 无参构造方法,因此不需要传值
Person instance = (Person) constructor3.newInstance();
System.out.println("无参构造"+instance);
System.out.println("===============================动态加载 类名 和方法===============================");
Properties prop = new Properties();
prop.load(new FileReader("src/main/resources/class.txt"));
String classname = prop.getProperty("classname");
String methodname = prop.getProperty("methodname");
Class<?> perClazz1 = null;
try {
perClazz1 = Class.forName(classname);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
method = perClazz1.getMethod(methodname);
System.out.println("===>反射读取配置文件并调用");
method.invoke(perClazz1.newInstance());
System.out.println("===============================反射可以 越过泛型检查===============================");
System.out.println("虽然可以通过反射 访问private等访问修饰符不允许访问的属性/方法,也可以忽略掉泛型的约束;" +
"但实际开发 不建议这样使用,因此可能造成程序的混乱。");
ArrayList<Integer> list = new ArrayList<>();
list.add(123);
list.add(3);
list.add(2);
// list.add("zs") ;
Class<?> listClazz = list.getClass();
method = listClazz.getMethod("add", Object.class);
method.invoke(list, "zs...");
System.out.println("反射可以 越过泛型检查===>"+list);
System.out.println("===============================使用工具类复制===============================");
Person person = new Person();
PropertyUtil.setProperty(person, "name", "长草颜团子");
PropertyUtil.setProperty(person, "age", 18);
Student stu = new Student();
PropertyUtil.setProperty(stu, "score", 98);
System.out.println(person.toString());
System.out.println(stu.getScore());
}
@Test
public void test2() throws InstantiationException, IllegalAccessException, NoSuchMethodException,
NoSuchFieldException, InvocationTargetException, IOException {
System.out.println("************************反射获取类的实例,并操作************************");
demo01();
}
}
3项目结构示意图
该博客围绕Java反射展开,介绍了通过反射获取类以及获取反射类实例后的操作,还给出了项目结构示意图。同时提供了参考代码的链接、springboot版本代码链接,以及腾讯课堂和网易云课堂的相关视频教程链接。
221

被折叠的 条评论
为什么被折叠?



