zoukankan      html  css  js  c++  java
  • 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); } }

      

  • 相关阅读:
    JVM
    OLAP
    rocketMq学习
    redis的使用小记
    CRT配置端口转发
    冒泡排序
    spring AOP-切面编程
    linux下对jar包和war包进行重新打包
    oracle-sql性能优化
    遍历List,根据子项的某个属性分组
  • 原文地址:https://www.cnblogs.com/-gongxue/p/14484783.html
Copyright © 2011-2022 走看看