zoukankan      html  css  js  c++  java
  • 关于反射

    一、Class类

    • 在面对对象编程中,万事万物皆对象,但是类本身又是谁的对象呢? 他是java.lang.Class的对象
    • 获取类类型的3种方法
    1. 通过对象类的对象获取
    Foo foo = new Foo();
    Class class1 = foo.getClass();
    
    1. 通过类名获取
    Class class2 = Foo.class;
    
    1. 还是通过类名获取,但是要try catch, 并且要转换类型
    try {
    	Class class3 = (Class) Class.forName("Foo");
    } catch (ClassNotFoundException e) {
    	// TODO Auto-generated catch block
    	e.printStackTrace();
    }
    

    二、获取类的方法信息

    • 一个成员方法就是Method类的对象
    • getMethods()是获得该类的所有public方法,包括从父类继承来的方法
    Method[] methods1 = class1.getMethods();
    
    • getDeclaredMethods()是获取当前类自己声明的成员方法,不包含父类继承来的,但是不问访问权限
    Method[] methods2 = class1.getDeclaredMethods();
    
    • 得到返回值类型,先得到返回值类型的类类型,再获得名字
    Class returnType = methods1[i].getReturnType();
    String returnTypeName = returnType.getName();
    
    
    • 得到方法名
    for (int i = 0; i < methods1.length; i++) {
    	System.out.println(methods1[i].getName());
    }
    
    • 得到参数类型,因为参数可能有多个,所以先得到参数列表,再遍历它得到参数类型的名字
    Class[] paramTypes = methods1[i].getParameterTypes();
    	for (Class paramType : paramTypes) {
    		String paramTypeName = paramType.getName();
    }
    

    三、获取成员变量的信息

    • 成员变量是java.lang.reflect.Field类的对象
    • getFields()获得的是所有public的成员变量
    Field[] fields1 = class1.getFields();
    
    • getDeclaredFields()获得的是自己声明的所有的成员变量
    Field[] fields2 = class1.getDeclaredFields();
    
    • 获得成员变量类型的名称
    for (Field field : fields2) {
    	Class fieldType = field.getType();
    	String fieldTypeName = fieldType.getName();
    }
    
    • 获得成员变量名称
    String fieldName = field.getName();
    

    四、获取构造函数的信息

    • 构造函数是java.lang.reflect.Constructor的对象
    • 获得构造函数,方法基本同上
    Constructor[] constructors1 = class1.getConstructors();
    Constructor[] constructors2 = class1.getDeclaredConstructors();
    
    • 获得构造参数类型
    for (Constructor constructor : constructors2) {
    	Class[] paramTypes = constructor.getParameterTypes();
    	for (Class paramType : paramTypes) {
    		String paramTypeName = paramType.getName();
    	}
    }
    
    • 获得构造方法名称
    String csName = constructor.getName();
    

    五、 反射调用方法

    public class A {
    	public void print(int a, int b) {
    		System.out.println(a + b);
    	}
    	
    	public void print(String a, String b) {
    		System.out.println(a.toUpperCase() + b.toLowerCase());
    	}
    }
    
    • 获取方法对象,先获得类类型,再操作
    A a1 = new A();
    Class clazz = a1.getClass();
    // 这里第一个参数表示方法名,后面的是参数的类类型,如果没参数,就不传
    // 要唯一确定一个方法,就得确定他的方法名和参数类型
    Method m = clazz.getMethod("print", int.class, int.class);
    
    • 反射调用方法
    // 这里是方法对象调用invoke方法,第一个参数是对象,后面的是参数,没参数就不写
    //普通调用方法为:a1.print(10,20);
    m.invoke(a1, 10, 20);
    

    六、通过反射操作绕过编译,以集合泛型为例

    public class MethodDemo1 {
    	public static void main(String[] args) {
    		ArrayList list1 = new ArrayList();
    		ArrayList<String> list2 = new ArrayList<String>();
    		Class c1 = list1.getClass();
    		Class c2 = list2.getClass();
    		/**
    		 * 反射的操作都是在编译之后进行的
    		 * c1 == c2 返回ture 说明编译之后集合的泛型是去泛型话的
    		 * java种集合的泛型,是防止错误输入的,只再编译阶段有效,绕过编译就无效了
    		 */
    		// list2.add(29); 错误
    		System.out.println(c1 == c2); // true
    		
    		/**
    		 * 通过方法的反射操作来绕过编译
    		 * c1 == c2 所有下面用c1还是c2都一样
    		 */
    		try {
    			Method m = c2.getMethod("add", Object.class);
    			// 绕过编译操作就绕过了泛型
    			m.invoke(list2, 100);
    			System.out.println(list2);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} 
    		
    	}
    }
  • 相关阅读:
    配置Nginx和Apache允许指定域名CORS跨域访问
    当遇到npm ERR! Unexpected end of JSON input while parsing near……时的解决办法
    基于thinkphp开发的项目部署到由宝塔面板创建的LNMP服务器上解决路径出错问题
    在ThinkPHP框架(5.0.24)下引入Ueditor并实现向七牛云对象存储上传图片同时将图片信息保存到MySQL数据库,同时实现lazyload懒加载
    为Sublime Text 3设置优雅的字体
    windows7x64系统中配置mysql5.7.17为本地开发环境(win2008类似)
    SQL Server实现数据的递归查询
    在.net程序中使用System.Net.Mail来发送邮件
    在 Ubuntu 13.10 中搭建Java开发环境
    Windows 系统下载安装 ZooKeeper
  • 原文地址:https://www.cnblogs.com/xgzzzy16/p/9808965.html
Copyright © 2011-2022 走看看