Java的反射机制

2019-07-31  本文已影响0人  Roct

Class简介

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

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

Class实例化

public final Class<?> getClass();
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";
    }
}
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);
    }
}
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());
    }
}

上一篇下一篇

猜你喜欢

热点阅读