zoukankan      html  css  js  c++  java
  • 细说java系列之反射

    什么是反射

    反射机制允许在Java代码中获取被JVM加载的类信息,如:成员变量,方法,构造函数等。
    在Java包java.lang.reflect下提供了获取类和对象反射信息的相关工具类和接口,如:Field,Method,Constructor等。

    使用反射可以做什么事情

    反射通常被用于需要检查或修改应用程序运行时行为的编程中,它是一个非常有用的技术。
    具体来讲,可以在如下场景中使用反射机制:

    • 功能扩展,应用程序可以通过反射创建一个具备完整限定名的类实例,从而使用一个外部的用户自定义的类。
    • 在可视化的开发环境中浏览类信息,其实在eclipse中通过快捷键Ctrl + O显示的类信息就是利用反射机制实现的。
    • 用于程序调试器和测试工具

    反射的缺点

    虽然反射机制可以增强应用程序的功能和使用场景,但并非在任何情况下都适合使用的,因为反射机制本身存在一些固有的缺点。

    1. 性能损耗,反射需要动态解析类型,相比起不使用反射的情况是存在性能损耗的,所以在性能比较敏感或重要的应用程序中不要使用反射。
    2. 安全限制,反射需要的运行时权限在安全管理器(SecurityManager)下是被禁止的,比Applet程序中。
    3. 类结构被暴露,由于反射允许在非反射代码中执行一些非法操作,打破了Java原本的抽象模型,可能会影响到平台的行为与升级。

    应用实践

    /**
     * 利用反射机制获取被JVM加载的类信息,实例化类对象。
     * @desc org.chench.test.java.UserReflector
     * @author chench9@lenovo.com
     * @date 2017年11月30日
     */
    public class UserReflector {
    	public static void main(String[] args) throws Exception {
    		String className = "org.chench.test.java.User";
    		
    		// 通过类的完整限定名获取其Class对象
    		Class<?> userClass = Class.forName(className);
    		
    		// 使用反射机制获取类的构造函数列表
    		Constructor[] constructorArr =  userClass.getConstructors();
    		for(Constructor constructor : constructorArr) {
    			// 构造函数的名称
    			String name = constructor.getName();
    			System.out.println("constructor name: " + name);
    			
    			// 构造函数的参数个数
    			int count = constructor.getParameterCount();
    			System.out.println("constructor parameter count: " + count);
    			
    			// 构造函数的参数列表
    			Parameter[] parameters = constructor.getParameters();
    			for(Parameter parameter : parameters) {
    				// 获取参数类型
    				Class<?> parameterType = parameter.getType();
    				// 获取参数名
    				String parameterName = parameter.getName();
    				System.out.println(parameterName + " Type: " + parameterType);
    			}
    			
    			// 通过构造函数实例化类对象
    			if(count <= 0) {
    				User user =	(User) constructor.newInstance();
    				System.out.println("user instance: " + user);
    			}else if(count == 1) {
    				User user = (User) constructor.newInstance(new Object[] {"Zhang San"});
    				System.out.println("user instance: " + user);
    			}else if(count == 2) {
    				User user = (User) constructor.newInstance(new Object[] {"Li Si", 26});
    				System.out.println("user instance: " + user);
    			}
    			System.out.println("----------");
    		}
    		
    		// 使用反射机制获取类的成员变量
    		Field[] fields = userClass.getDeclaredFields();
    		for(Field field : fields) {
    			// 变量类型
    			Class<?> fieldType = field.getType();
    			// 变量名称
    			String fieldName =	field.getName();
    			// 变量修饰符,private:2,public:1, protected: 4,默认类型: 0
    			int fieldModifier = field.getModifiers();
    			System.out.println("field info, name: " + fieldName + ", type: " + fieldType + ", modifier: " + fieldModifier);
    		}
    		
    		// 使用反射机制获取类的方法
    		Method[] methods = userClass.getDeclaredMethods();
    		for(Method method : methods) {
    			// 方法返回值类型
    			Class<?> returnType = method.getReturnType();
    			// 方法名
    			String methodName = method.getName();
    			// 方法参数个数
    			int count = method.getParameterCount();
    			System.out.println("method info, name: " + methodName + ", return type: " + returnType + ", parameter count: " +count);
    		}
    	}
    }
    

    实际上,在应用编程中使用反射机制最多的场景主要是如下2个方面:

    1. 在注解解析器中通过反射获取类,方法或成员变量的注解信息。
    2. 在动态代理类中使用反射机制调用方法执行。

    【参考】
    https://docs.oracle.com/javase/tutorial/reflect/TOC.html

  • 相关阅读:
    element ui 表单清空
    element ui 覆盖样式 方法
    element ui 修改表单值 提交无效
    element ui 抽屉里的表单输入框无法修改值
    element ui 抽屉首次显示 闪烁
    css 左侧高度 跟随右侧内容高度 自适应
    PICNUF框架
    elementui 抽屉组件标题 出现黑色边框
    vue 子组件跨多层调用父组件中方法
    vue 编辑table 数据 未点击提交,table里的数据就发生了改变(深拷贝处理)
  • 原文地址:https://www.cnblogs.com/nuccch/p/7928336.html
Copyright © 2011-2022 走看看