zoukankan      html  css  js  c++  java
  • 利用反射特性完成对象的拷贝

    反射是jdk1.5之后提供的一种可以让我们在类运行时动态获得类信息的机制,在类加载时,任何一个java类都存在一个java.lang.Class对象,反射即将类中的成分反射成对应的类型(属性,方法,构造器,注解等)对象,就和类自身照镜子一样,通过这种机制和泛型的结合,我们可以实现对任意一种类型对象的拷贝,废话不多说,直接上代码

    public class CopyDemo {

    /**
    * 实现任意对象的拷贝,返回的具体类型的对象
    * @param <T>
    * @param source
    * @param t
    * @return
    */
    public static <T> T clone(Object source,Class<T> t) {
    T obj = null;
    try {
    //基于目标类型实例化对象
    obj = t.newInstance();

    Field[] fields = t.getDeclaredFields();
    for (Field f : fields) {
    String fname = f.getName();
    // 分别获取属性对应的setter/getter方法名称
    String sname = "set" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
    String gname = "get" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
    //如果属性是boolean类型的,则get方法应该改成is
    if("boolean".equals(f.getType().getCanonicalName())) {
    gname = "is" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
    }
    //获取方法对象
    Method methodSet = t.getMethod(sname, f.getType());
    Method methodGet = t.getMethod(gname);

    methodSet.invoke(obj, methodGet.invoke(source));
    }
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (SecurityException e) {
    e.printStackTrace();
    } catch (IllegalArgumentException e) {
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    e.printStackTrace();
    }

    return obj;
    }


    public static void main(String[] args) {

    Dog d = new Dog();
    d.setId(1);
    d.setName("旺财");
    d.setAge(5);
    d.setType("二哈");

    Dog user = CopyDemo.clone(d, Dog.class);
    System.out.println(user.getName());
    }

    }

    开始分析代码:

       public static <T> T clone(Object source,Class<T> t)  传入任意类型的对象,转换成指定类型(Class<T> t),返回一个对应泛型的对象

          先利用传入的Class类对象,获取该类的新对象  obj = t.newInstance();  

    接着就是再把原对象的属性值传给obj

    先通过getDeclaredField()方法获取指定类中所有属性集合  Field[] fields = t.getDeclaredFields();

    通过 

    String sname = "set" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
    String gname = "get" + fname.substring(0, 1).toUpperCase() + fname.substring(1);

    这两步操作,可以获得指定类非Boolean类型属性的set和get方法.

    如果有Boolean类型的属性可以加上一个判断获得:

    if("boolean".equals(f.getType().getCanonicalName())) {
    gname = "is" + fname.substring(0, 1).toUpperCase() + fname.substring(1);
    }

    有了方法名后 我们就可以通过getMethod获得指定的方法了

    Method methodSet = t.getMethod(sname, f.getType()); // set方法中有参数 所以出了方法名之外还有方法的参数类型来确定方法
    Method methodGet = t.getMethod(gname);

    最后先通过Object returnVal = methodGet.invoke(source) 来获得原对象某属性的值 

    再用 methodSet(obj,returnVal) 将source某属性的值赋给obj对象里

    最后的最后 将 obj对象返回

    最后的最后的最后 , 附上运行截图

    今天你学到东西了吗?!

  • 相关阅读:
    TSQL入门(msdn)
    在代码中,获取Entity Framework生成的TSQL查询语句
    Code First(一)
    UDPClient的用法
    Building Applications that Can Talk(转)
    Asynchronous Web and Network Calls on the Client in WPF(摘录)
    DropBox能正常使用了
    显示GIF图标报错:“A generic error occurred in GDI+.”
    第 2 篇Scrum 冲刺博客
    第 1 篇 Scrum 冲刺博客
  • 原文地址:https://www.cnblogs.com/j-1-z-2-s-3/p/13418884.html
Copyright © 2011-2022 走看看