java 反射机制详解

来源:互联网 发布:linux中进程怎么调度 编辑:程序博客网 时间:2024/05/27 09:47

java 反射:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。

java 反射类加载的生命周期:

在程序执行中JVM通过装载,链接,初始化这3个步骤完成。
类的装载是通过类加载器完成的,加载器将.class文件的二进制文件装入JVM的方法区,并且在堆区创建描述这个类的java.lang.Class对象。
 但是同一个类只会被类装载器装载以前
链接:就是把二进制数据组装为可以运行的状态。
链接分为:校验,准备,解析这3个阶段
校验:一般用来确认此二进制文件是否适合当前的JVM(版本),
准备:就是为静态成员分配内存空间,。并设置默认值
解析:指的是转换常量池中的代码作为直接引用的过程,直到所有的符号引用都可以被运行程序使用(建立完整的对应关系)
完成之后,类型也就完成了初始化,初始化之后类的对象就可以正常使用了,直到一个对象不再使用之后,将被垃圾回收,释放空间。
当没有任何引用指向Class对象时就会被卸载,结束类的生命周期

package com.bjhy.platform.criminal.search.report.test;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.LinkedHashMap;import java.util.List;import com.bjhy.platform.criminal.search.core.annotation.ColumnConfig;/** * java反射 * @author wbw * */public class MyReflect {/** *获取一个领域对象的完整包名和类名  * @param className 领域对象 * @return 领域对象完整包名和类名 */public static String getClassName(Class<?> clzz){return clzz.getName();}/** * jvm运行时期获取指定实体类的属性,属性类型 * @param clzz 类名 * @return 类属性、属性类型 */public static String getClassField(Class<?> clzz){Field[] fields = clzz.getFields();StringBuffer sb = new StringBuffer();for(Field field :fields){//属性名称sb.append(field.getName());// 属性类型sb.append(field.getType().getName());sb.append(",");}String str = sb.substring(0, sb.length() - 1);return str;}/** * 获取指定实体类的父类 * @param clzz 指定的实体类 * @return 实体类的父类 */public static String getSuperClassName(Class<?> clzz){return clzz.getSuperclass().getName();}/** * 反射调用静态方法 * @param className 实体类的完整包名和类名 */public static void getStaticMethod(String className){Class cls = null;try {cls = Class.forName(className);Method sm = cls.getDeclaredMethod("hello", int.class,String.class);sm.invoke(cls, 20,"xw");} catch (Exception e) {e.printStackTrace();}}/** * 反射为实体类private的属性赋值 * @param className */public static void setFieldValue(String className){Class cls = null;try {cls = Class.forName(className);Object user = cls.newInstance();Field field = cls.getDeclaredField("name");field.setAccessible(true);//设置字段为允许访问field.set(user, "xw");System.out.println(field.get(user));} catch (Exception e) {e.printStackTrace();}}/** *  * 获取实体类的类加载器 * java 有三种类加载器 * 1.Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。   2.Extension ClassLoader 用来进行扩展类的加载,一般对应的是jre\lib\ext目录中的类   3.AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 * @param clzz * @return */public static String getClassLoader(Class<?> clzz){return clzz.getClassLoader().getClass().getName();}/** * 工厂内部类,一般的工厂模式都是通过判断传入的对象类型而不做不同的操作,但是在增加多个子类的时候,就需要频繁的修改工厂类, * 但是如果使用反射机制将会在不改变工厂类的情况下操作子类 * @author wbw * */class Factory{/** * 一般情况下的工厂模式 * @param className  * @return */@SuppressWarnings("unused")public User demo1(String className){User user = null;if(className.equals("normal")){return user = new User();}else if(className.equals("ammin")){return user = new ManageUser();}return null;}/** * 反射工厂模式 * @param className * @return */public User demo(String className) throws Exception{return (User) Class.forName(className).newInstance();}}/**    * 根据实体类名获取属性名称和使用自定义注解设置的属性中文名称    * @param clzz 实体类名    * @return List<Map<String,Object>>      */public static List<LinkedHashMap<String,Object>>   initAnnoFieldDic(Class<?> clzz){    //使用List<LinkedHashMap<String,Object>>用于存储字段和中文值的集合//LinkedHashMap<String,Object> key为类.属性,value为属性的中文名称List<LinkedHashMap<String,Object>> fieldList = new ArrayList<>();LinkedHashMap<String,Object> valueMap = new LinkedHashMap<>();           //获取对象中所有的Fields            Field[] fields = clzz.getDeclaredFields();            //循环实体类字段集合,获取标注自定义注解@ColumnConfig的属性        for (Field field : fields) {        if(field.isAnnotationPresent(ColumnConfig.class)){        //获取字段名        String fieldNames = clzz.getSimpleName()+"."+field.getName();         //获取字段注解         ColumnConfig columnConfig = field.getAnnotation(ColumnConfig.class);         //判断是否已经获取过该code的字典数据 避免重复获取         if(valueMap.get(columnConfig.description())==null){         valueMap.put(fieldNames, columnConfig.description());         }        }        }        fieldList.add(valueMap);return fieldList;}}

 Class文件只是一种静态格式的二进制流,它只有被虚拟机加载进内存解析之后才会生成真正的运行时的结构,因此,搞清楚类加载机制不但有助于我们加深理解Class文件中各个字段的含义,同时也有利于我们更深入的了解JAVA。

最后附上java反射类加载图,便于更好的理解


0 0