美文网首页
Java的反射机制

Java的反射机制

作者: Roct | 来源:发表于2019-07-31 11:01 被阅读0次

    Class简介

    反射之中所有的核心操作都是通过Class类对象来展开的, 可以说Class类对象是反射操作的根源所在.
    定义

    public final class Class<T> extends Object implements 
    Seralizable, GenerircDeclaration, Type, AnnotatedElement
    

    Class实例化

    • [Object支持] Object类可以根据实例化对象获取Class对象:
      • 缺点: 如果现在只是想获得Class类对象, 则必须产生指定类对象以后获得, 会造成一个无用的类对象产生
    public final Class<?> getClass();
    
    • [JVM直接支持] 采用类.class的形式实例化
    • [Class类支持]Class类中提供了一个static方法:
    public static Class <?> forName(String className) throws ClassNotFoundException
    

    反射实例化对象

    创建一个单独的packagecn, cn中有一个类叫Person

    public class Person {
        public Person() {
            System.out.println("*********实例化Person***********");
        }
    
        @Override
        public String toString() {
            return "Person.toString";
        }
    }
    
    • JDK1.9之前:
    public T newInstance() throws InstantiationException, IllegalAccessException
    

    反射实例化Person

    public class Main {
        public static void main(String[] args) throws Exception {
            Class<?> cls = Class.forName("cn.Person");
            Object obj = cls.newInstance();
            System.out.println(obj);
        }
    }
    
    • JDK1.9以后
    clazz.getDeclaredConstructor().newInstance();
    

    反射实例化Person

    public class Main {
        public static void main(String[] args) throws Exception {
            Class<?> cls = Class.forName("cn.Person");
            Object obj = cls.getDeclaredConstructor().newInstance();
            System.out.println(obj);
        }
    }
    

    反射与工厂模式

    反射与工厂模式代码实现

    interface IMessage {
        public void send();
    }
    class INetMessage implements IMessage {
        @Override
        public void send() {
            System.out.println("发送一条消息");
        }
    }
    interface IService {
        public void service();
    }
    class HouseService implements IService {
        @Override
        public void service() {
            System.out.println("发起一个服务");
        }
    }
    class Factory {
        private Factory() {}
        public static <T> T getInstance(String className, Class<T> clazz) {
            T instance = null;
            try {
                instance = (T)Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return instance;
        }
    }
    public class Main {
        public static void main(String[] args) throws Exception {
            HouseService service = Factory.getInstance("HouseService", HouseService.class);
            service.service();
        }
    }
    
    反射与工厂模式

    反射与单例设计模式

    单例设计模式的核心本质在于: 类内部的构造方法私有化, 在类的内部产生实例化对象之后通过static获取实例化对象进行调用.

    饿汉式单例设计

     class Singleton{
        private static Singleton modle = new Singleton ();//声明对象同时私有化
        private Singleton (){}//构造函数私有化
        public static Singleton getInstance(){//向外声明访问该类对象的方法
            return modle;
        }
    }
    

    懒汉式单例设计

    class Singleton {
        private static Singleton instance = null;
        private Singleton() {}
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
        public void print() {
            System.out.println("这是一个懒汉式的单例设计");
        }
    }
    
    public class Main {
        public static void main(String[] args) throws Exception {
            Singleton single = Singleton.getInstance();
            single.print();
        }
    }
    

    懒汉式单例存在的问题
    单例模式的最大特点是在运行当中只存在一个对象, 但是在多线程中就可以产生多个实例化对象了, 那么此时就不是单例设计模式了

    多线程下的单例
    问题产生的核心就是多线程进行了多次单例的实例化, 解决问题的核心是进行同步处理, synchronized加锁

    最标准懒汉式单例

    class Singleton {
        private static volatile Singleton instance = null;
        private Singleton() {}
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
        public void print() {
            System.out.println("这是一个懒汉式的单例设计");
        }
    }
    
    public class Main {
        public static void main(String[] args) throws Exception {
            Singleton single = Singleton.getInstance();
            single.print();
        }
    }
    

    反射获取类结构信息

    获取包名称

    public Package getPackage();
    

    获取继承父类

    public Class <? super T> getSuperclass();
    

    获取实现父接口

    public Class<?>[] getInterfaces()
    

    获取构造方法

    • 实例化方法替代
    clazz.getDeclaredConstructor().newInstance();
    
    • 反射获取所有构造方法
    public Constructor<?>[] getDeclaredConstructors() throws SecurityException;
    
    public Constructor<?>[] getConstructors() throws 
    SecurityException
    
    • 获取指定构造方法
    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
    throws NoSuchNMethodException, SecurityException;
    
    public Constructor<T> getConstructors(Class<?>... parameterTypes) 
    throws NoSuchNMethodException, SecurityException;
    

    反射获取普通方法

    如果想通过反射调用普通方法, 那么必须类之中要提供实例化对象

    • 获取全部方法
    public Method[] getMethods() throws SecurityException;
    
    • 获取指定方法
    public Method getMethod(String name, Class<?>... paramterTypes) 
    throws NoSuchMethodException, SecurityException;
    
    • 获取本类全部方法
    public Method[] getDeclaredMethods() throws SecurityException;
    
    • 获取本类指定方法
    public Method getDeclaredMethod(String name, Class<?>... paramterTypes) 
    throws NoSuchMethodException, SecurityException;
    

    反射获取成员

    • 获取本类全部成员
    public Field[] getDeclaredFields() throws SecurityException;
    
    • 获取本类指定成员
    public Field getDeclaredField(String name) throws
    NoSuchMethodException, SecurityException;
    
    • 获取父类全部成员
    public Field[] getFields() throws SecurityException;
    
    • 获取父类指定成员
    public Field getField(String name) throws
    NoSuchMethodException, SecurityException;
    

    Unsafe工具类(不安全的操作)

    Unsafe的主要特点是可以利用反射来获取对象, 并且直接使用底层的C++来代替JVM执行, 即: 可以绕过JVM的相关对象的管理机制, 如果一旦使用了Unsafe类, 那么将无法使用JVM的内存管理机制和垃圾回收处理

    构造方法

    private Unsafe() {}
    

    私有常量

    private static final Unsafe theUnsafe = new Unsafe();
    

    属性自动赋值实现思路

    在传统开发之中, 一个类的属性, 要通过settergetter方法赋值和获取值, 如果属性多, 那么将带来大量的重复代码和很大的不方便. 所以要通过反射来实现自动赋值

    自动赋值思路
    class Company {
        private String name;
        private String createDate;
    
        public void setCreateDate(String createDate) {
            this.createDate = createDate;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getCreateDate() {
            return createDate;
        }
    
        public String getName() {
            return name;
        }
    }
    
    class Dept {
        private String dname;
        private String loc;
        private Company company;
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        public void setLoc(String loc) {
            this.loc = loc;
        }
    
        public void setCompany(Company company) {
            this.company = company;
        }
    
        public Company getCompany() {
            return company;
        }
    
        public String getLoc() {
            return loc;
        }
    
        public String getDname() {
            return dname;
        }
    }
    
    class Emp {
        private Dept dept;
        private String ename;
        private String job;
        private long empno;
        private Double salary;
        private Date birthDay;
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        public Dept getDept() {
            return dept;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public void setJob(String job) {
            this.job = job;
        }
    
        public void setBirthDay(Date birthDay) {
            this.birthDay = birthDay;
        }
    
        public void setEmpno(long empno) {
            this.empno = empno;
        }
    
        public void setSalary(Double salary) {
            this.salary = salary;
        }
    
        public String getEname() {
            return ename;
        }
    
        public String getJob() {
            return job;
        }
    
        public Date getBirthDay() {
            return birthDay;
        }
    
        public Double getSalary() {
            return salary;
        }
    
        public long getEmpno() {
            return empno;
        }
    }
    
    class ClassInstanceFactory {
        private ClassInstanceFactory() {
        }
    
        /**
         * 实例化对象的创建方法, 该对象可以根据传入的字符串结构"属性:内容|属性:内容"
         *
         * @param clazz 要进行反射实例化的类, 有Class就可以反射实例化对象
         * @param value 要设置给对象的属性内容
         *              return 一个已经配置好属性内容的Java类对象
         */
        public static <T> T create(Class<?> clazz, String value) {
            try {
                Object obj = clazz.getDeclaredConstructor().newInstance();
                BeanUtils.setValue(obj, value);
                return (T) obj;
            } catch (Exception e) {
                return null;
            }
        }
    }
    
    // 实现属性的首字母大写
    class StringUtils {
        /**
         * 首字母大写字符串
         *
         * @param str 传入的字符串
         * @return 一个大写首字母的字符串
         */
        public static String initcap(String str) {
            if (str == null || "".equals(str)) {
                return str;
            }
            if (str.length() == 1) {
                return str.toUpperCase();
            } else {
                return str.substring(0, 1).toUpperCase() + str.substring(1);
            }
        }
    }
    
    // 实现赋值
    class BeanUtils {
        private BeanUtils() {
        }
    
        public static void setValue(Object obj, String value) {
            String results[] = value.split("\\|"); // 按照|进行分割
            for (int i = 0; i < results.length; i++) { // 循环设置属性内容
                String attval[] = results[i].split(":"); // 获取属性名称和内容
                System.out.println(attval[0].toString());
                if (attval[0].contains(".")) { // 多级配置
                    String temp[] = attval[0].split("\\.");
                    Object currentObject = obj;
                    for (int j = 0; j < temp.length - 1; j++) {
                        try {
                            // 获取属性对应的get方法
    //                        System.out.println("sss:" + temp[j]);
                            Method getMethod = currentObject.getClass().getDeclaredMethod("get" +
                                    StringUtils.initcap(temp[j]));
                            // 调用get方法
                            Object tempObject = getMethod.invoke(currentObject);
                            // 调用对于的get方法, 如果返回不是空, 那么就不需要实例化
                            if (tempObject == null) {
                                // 获取该属性的类型
                                Field field = currentObject.getClass().getDeclaredField(temp[j]);
                                // 获取set方法
                                Method method = currentObject.getClass().getDeclaredMethod("set" +
                                        StringUtils.initcap(temp[j]), field.getType());
                                Object newObject = field.getType().getDeclaredConstructor().newInstance();
                                method.invoke(currentObject, newObject);
                                // 实例化对象
                                currentObject = newObject;
                            } else {
                                currentObject = tempObject;
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    try {
                        Field field = currentObject.getClass().getDeclaredField(temp[temp.length - 1]); // 获取属性
                        Method setMethod = currentObject.getClass().getDeclaredMethod("set" +
                                StringUtils.initcap(temp[temp.length - 1]), field.getType());  // 获取方法
    //                System.out.println("field.getType().getName()::" + field.getType().getName());
                        Object val = BeanUtils.convertAttributeValue(field.getType().getName(), temp[temp.length - 1]);
                        setMethod.invoke(currentObject, attval[1]); //  调用方法
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        Field field = obj.getClass().getDeclaredField(attval[0]); // 获取属性
                        Method setMethod = obj.getClass().getDeclaredMethod("set" +
                                StringUtils.initcap(attval[0]), field.getType());  // 获取方法
    //                System.out.println("field.getType().getName()::" + field.getType().getName());
                        Object val = BeanUtils.convertAttributeValue(field.getType().getName(), attval[1]);
                        setMethod.invoke(obj, val); //  调用方法
                    } catch (Exception e) {
    //                e.printStackTrace();
                    }
                }
            }
        }
    
        private static Object convertAttributeValue(String type, String value) {
            if (type == "int" || "java.lang.Integer".equals(type)) {
                return Integer.parseInt(value);
            } else if (type == "double" || "java.lang.Double".equals(type)) {
                return Double.parseDouble(value);
            } else if (type == "long" || "java.lang.long".equals(type)) {
                return Long.parseLong(value);
            } else if ("java.util.Date".equals(type)) {
                SimpleDateFormat format = null;
                if (value.matches("\\d{4}-\\d{2}-\\d{2}")) {
                    System.out.println("???");
                    format = new SimpleDateFormat("yyyy-MM-dd");
                } else if (value.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
                    format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                } else {
                    return new Date();
                }
                try {
                    return format.parse(value);
                } catch (ParseException e) {
    //                e.printStackTrace();
                    return new Date();
                }
            } else {
                return value;
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) throws Exception {
            /**
             * dept.dname == Emp的实例化对象.getDept().setDname("工程技术部")
             * dept.company.name:ayd == Emp的实例化对象.getDept().getCompany().setName("ayd")
             */
            Emp emp = ClassInstanceFactory.create(Emp.class, "dept.dname:工程技术部|dept.company.name:ayd" +
                    "|empno:2827892|ename:小强|job:程序员" +
                    "|salary:2937829|birthDay:1989-10-10");
            System.out.println("部门:" + emp.getDept().getDname() + ",公司:" + emp.getDept().getCompany().getName() + ",编号:" + emp.getEmpno() + ", 姓名:" + emp.getEname() + ", 工作:" + emp.getJob()
                    + ", 工资:" + emp.getSalary() + ", 生日:" + emp.getBirthDay());
    
    //        System.out.println(emp.getDept());
    //        System.out.println(emp.getDept().getCompany());
        }
    }
    
    

    相关文章

      网友评论

          本文标题:Java的反射机制

          本文链接:https://www.haomeiwen.com/subject/hoymrctx.html