0305 反射

1、通过反射获取构造方法

构造方法使用类Constructor表示

返回一个构造方法

public Constructor<T> getConstructor(Class<?>... parameterTypes) 获取public修饰, 指定参数类型所对应的构造方法

public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 获取指定参数类型所对应的构造方法(包含私有的)

通过字节码文件对象调用上述两个方法就能获取到构造方法对象,获取构造方法对象之后需要调用Constructor中的newInstance方法去通过构造方法创建对象

代码展示

	public static void main(String[] args) throws 
	ClassNotFoundException, NoSuchMethodException, 
	SecurityException, InstantiationException, 
	IllegalAccessException, IllegalArgumentException, 
	InvocationTargetException {
		//获取Person的字节码文件对象
		Class c=Class.forName("com.oracle.demo02.Person");
		//获取构造方法对象
		Constructor con=c.getDeclaredConstructor(String.class);
		//取消java检查
		con.setAccessible(true);
		//创建对象
		//暴力反射(不推荐使用 破坏了封装性)
		Person p=(Person)con.newInstance("小红");
		p.eat();
		
	}

  上述中Person中获取的是一个私有的构造方法,私有构造方法不允许创建对象,那只能调用Constructor的父类中的setAccessible方法去开启 取消java检查,那就java就不会检查是不是私有的构造创建对象

2、通过反射获取成员变量

类中的成员变量使用类Field表示

返回一个成员变量

public Field getField(String name) 获取指定的 public修饰的变量

public Field getDeclaredField(String name) 获取指定的任意变量

代码展示

	public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
		//获取字节码文件兑现
		Class c=Class.forName("com.oracle.demo02.Person");
		//获取成员变量对象
		Field f=c.getField("name");
		//快速创建对象
		Object obj=c.newInstance();
		//给成员变量赋值
		f.set(obj, "你好");
		//取值
		System.out.println(f.get(obj));
	}

  上述代码中 我们获得了成员变量,那我们想给这个成员变量那就必须有一个对象,所以这里调用了Class类中的newInstance方法能够快速创建一个对象,那我们获取到成员变量的对象,那我们要给成员变量赋值,那么要调用Filed类中的 set方法去赋值,public void set(Object obj, Object value) 传一个指定object对象 传一个value值,取值是通过public Object get(Object obj)方法

3、通过反射获取成员方法并使用

类中的成员方法使用类Method表示

返回获取一个方法

public Method getMethod(String name, Class<?>... parameterTypes)获取public 修饰的方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)获取任意的方法,包含私有的

代码展示

	public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, 
IllegalArgumentException, InvocationTargetException { //获取字节码文件对象 Class c=Class.forName("com.oracle.demo02.Person"); //获取成员方法对象 Method m=c.getMethod("eat", String.class,int.class); //快速创建对象 Object obj=c.newInstance(); //执行方法 m.invoke(obj, "小红马",18); }

  在上述方法中同样运用到了快速创建对象的方法,获取到成员方法那么想使用的话需要调用Method类中public Object invoke(Object obj,  Object... args)方法

反射练习之泛型擦除

例如我们创建一个ArrayList<Integer> arr=new ArrayList<Integer>();集合 我们发现有泛型 arr.add(123); 可以正常运行,那么arr.add("abc");是不能运行的因为 泛型是integer 不能存String类型的数据,在java中有两种东西进不到内存中去 一个是注释,一个就是泛型,那么我们可以通过反射操作他的字节码文件 去将不属于这个泛型类型的数据存入到有泛型规范的集合中去

代码展示

	public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, 
IllegalArgumentException, InvocationTargetException { ArrayList<Integer> arr=new ArrayList<Integer>(); arr.add(123); //arr.add("abc"); //获取字节码文件对象 Class c=arr.getClass(); //获取成员方法对象 Method m=c.getMethod("add", Object.class); //执行方法 m.invoke(arr, "abc"); //遍历 for(Object obj:arr){ System.out.println(obj); } }

  

反射练习之配置文件

首先创建两个实体类

public class Student {

	public void study(){
		System.out.println("学生学习");
	}
}
public class Worker {

	public void work(){
		System.out.println("工人工作");
	}
}

  创建一个properties类文件

className=com.oracle.demo04.Worker
method=work

  创建一个测试类

public class Demo01 {

	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, 
IllegalAccessException, IllegalArgumentException, InvocationTargetException { //通用的方式 反射配置文件 //明确数据源 FileReader fr=new FileReader("src/com/oracle/demo04/pro.properties"); //创建集合 Properties pro=new Properties(); //将文件中的键值对度到集合中 pro.load(fr); //获取类名 String className=pro.getProperty("className"); //获取方法名 String methodName=pro.getProperty("method"); //获取字节码文件对象 Class c=Class.forName(className); //获取成员方法对象 Method m=c.getMethod(methodName); //快速创建对象 Object obj=c.newInstance(); //执行 m.invoke(obj); } }

  

posted @ 2021-03-05 10:36  公雪  阅读(108)  评论(0编辑  收藏  举报