java进阶(三):反射(1)——构造方法和属性的反射

来源:互联网 发布:大数据技术之企业发展 编辑:程序博客网 时间:2024/06/05 00:24

一、构造方法的反射——Constructor

先附上ChinaPerson接口和Person类

package com.reflect.net;public interface ChinaPerson {public static final String name = "邵小宝";public static int age = 26;public void sayChina();public void sayHello(String name, int age);}

package com.reflect.net;/** *  * Person.java * * @title  * @description * @author SAM-SHO  * @Date 2014-8-28 */public class Person implements ChinaPerson{private String name;private int age;private String sex;public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Person() {}public Person(String name) {this.name = name;}public Person(int age) {this.age = age;}public Person(String name, int age) {this.age = age;this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "[" + this.name + "  " + this.age + "]";}@Overridepublic void sayChina() {System.out.println("hello ,china,邵小宝");}@Overridepublic void sayHello(String name, int age) {System.out.println(name+"  "+age);}}


1、得到所有的构造方法:getConstructors()

2、得到单个构造方法:getConstructor()或者getConstructor(Object.class)

public static void main(String[] args) throws Exception {        Class<?> demo=null;        try{            demo=Class.forName("com.reflect.net.Person");        }catch (Exception e) {            e.printStackTrace();        }        //取得父类        Class<?> temp = demo.getSuperclass();        System.out.println("继承的父类为:   "+temp.getName());                        //取得构造方法        Constructor<?>cons[] = demo.getConstructors();        for (int i = 0; i < cons.length; i++) {            System.out.println("构造方法:  "+cons[i]);        }               //取得单个构造方法,调用的是Person无参的构造方法        Constructor<?> con = demo.getConstructor();       System.out.println("单个无参构造方法:  "+con);               //取得单个有参构造方法        Constructor<?> con2 = demo.getConstructor(String.class);       System.out.println("单个有参构造方法:  "+con2);                      //取得单个有参构造方法        Constructor<?> con3 = demo.getConstructor(String.class,int.class);       System.out.println("单个有参构造方法:  "+con3);                   }

3、通过构造方法创建对象

public static void main(String[] args) {        Class<?> demo=null;        try{            demo=Class.forName("com.reflect.net.Person");        }catch (Exception e) {            e.printStackTrace();        }        Person per1=null;        Person per2=null;        Person per3=null;        Person per4=null;        //取得全部的构造函数        Constructor<?> cons[]=demo.getConstructors();        try{        //顺序乱的,有可能报错            per1=(Person)cons[0].newInstance("邵小宝");            per2=(Person)cons[1].newInstance(20);            per3=(Person)cons[2].newInstance("邵小宝",20);            per4=(Person)cons[3].newInstance();                        //利用无参的构造方法,创建对象:Person person1 = new Person();            Constructor<?> con1 =demo.getConstructor();            Person person1 = (Person) con1.newInstance();            System.out.println(person1);                        //通过有参的构造函数,创建对象:Person person1 = new Person("SAM-SHO",28);            Constructor<?> con2 =demo.getConstructor(String.class,int.class);            Person person2 = (Person) con2.newInstance("SAM-SHO",28);            System.out.println(person2);                    }catch(Exception e){            e.printStackTrace();        }        System.out.println(per1);        System.out.println(per2);        System.out.println(per3);        System.out.println(per4);    }
//【运行结果】:/*[邵小宝  0] [null  20] [邵小宝  20] [null  0]  [null  0] [SAM-SHO  28] */


4、可以直接调用无参的构造方法:通过无参构造实例化对象
public static void main(String[] args) {        Class<?> demo=null;        try{            demo=Class.forName("com.reflect.net.Person");        }catch (Exception e) {            e.printStackTrace();        }        Person per=null;        try {        //直接调用无参的构造方法,默认会先调用默认的构造方法            per=(Person)demo.newInstance();        } catch (InstantiationException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }        per.setName("邵小宝");        per.setAge(20);        System.out.println(per);    }
【运行结果】:[邵小宝  20]但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:比如我定义了一个构造函数:public Person(String name, int age) {        this.age=age;        this.name=name;    }然后继续运行上面的程序,会出现:java.lang.InstantiationException: com.reflect.Person<span style="white-space:pre"></span>at java.lang.Class.newInstance0(Class.java:340)<span style="white-space:pre"></span>at java.lang.Class.newInstance(Class.java:308)<span style="white-space:pre"></span>at com.reflect.Hello3.main(Hello3.java:21)Exception in thread "main" java.lang.NullPointerException<span style="white-space:pre"></span>at com.reflect.Hello3.main(Hello3.java:29)所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数

二、成员变量的反射——Field

1、得到属性方法:getField(Striing str)和getFields(),但是不能得到私有属性,这时需要方法getDeclaredFields()和getDeclaredField(Striing str)

2、得到属性的类型:getType();类型的比较直接用“==”,不需要用equals。如field.getType() == String.class;

3、设置属性的值:set(Object obj, Object value);得到属性的值get(Object obj)。注意:设置和取值需要去操作某个对象。

public static void main(String[] args) throws Exception {        Class<?> demo = null;        try {            demo = Class.forName("com.reflect.net.Person");        } catch (Exception e) {            e.printStackTrace();        }        System.out.println("===============本类属性========================");        // 取得本类的全部属性        Field[] field = demo.getDeclaredFields();        for (int i = 0; i < field.length; i++) {            // 权限修饰符            int mo = field[i].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = field[i].getType();            System.out.println(priv + " " + type.getName() + " "                    + field[i].getName() + ";");        }                System.out.println("===============实现的接口或者父类的属性========================");        // 取得实现的接口或者父类的属性        Field[] filed1 = demo.getFields();        for (int j = 0; j < filed1.length; j++) {            // 权限修饰符            int mo = filed1[j].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = filed1[j].getType();            System.out.println(priv + " " + type.getName() + " "                    + filed1[j].getName() + ";");        }                //2-得到单个的属性:如得到name属性        Class<?> clazz = Class.forName("com.reflect.net.Person");//new 一个对象        Person person = (Person) clazz.newInstance();        Field name = clazz.getField("name");//得到Pserson实例的name的属性        Class<?> nameType = name.getType();        System.out.println("属性的类型  " + nameType);                name.set(person, "sam-sho");//设置属性的值                String value = (String) name.get(person);//需要去具体取某个对象上的值,get(person)方法        System.out.println("属性的值:" + value);                //3-得到私有属性:如果把Person的age属性设为private//      Field name = clazz.getField("age");//报错:Exception in thread "main" java.lang.NoSuchFieldException: age        Field dName = clazz.getDeclaredField("age");        dName.setAccessible(true);// 对私有属性的的暴力反射              dName.set(person, 99);                int ageValue =  (Integer)dName.get(person);System.out.println("私有属性的值" + ageValue);//综合使用:修改某个对象所有String成员变量的值changstringValue(person,'s','S');//sam-sho, s变成大写System.out.println(person);            }/** * 修改某个对象所有String成员变量的值:有"b",改成""; */private static void changstringValue(Object object,char a, char b) throws IllegalArgumentException, IllegalAccessException {Field[] arrField = object.getClass().getFields();for (Field field : arrField) {System.out.println(field.getType());//得到类型System.out.println(field.getName());// 因为是同一份字节码,用"==",而不需要equalsif(field.getType() == String.class) {String oldValue = (String) field.get(object);//得到旧的值String newValue = oldValue.replace(a,b);field.set(object, newValue);//设置新的值}}}
【输出】===============本类属性========================public java.lang.String name;private int age;private java.lang.String sex;===============实现的接口或者父类的属性========================public java.lang.String name;属性的类型  class java.lang.String属性的值:sam-sho私有属性的值99class java.lang.Stringname[Sam-Sho  99]

4、利用属性的反射,就可以写类似于BeanUtils的copyProperties()方法。
/** * 把对象b的值赋给对象a *  * @return Object */public Object transFields(Object a, Object b) {Class c1 = a.getClass();Class c2 = b.getClass();Field[] fieldsDest = c1.getDeclaredFields();Field[] fieldsOrg = c2.getDeclaredFields();AccessibleObject.setAccessible(fieldsDest, true);AccessibleObject.setAccessible(fieldsOrg, true);// logger.debug("----fieldDest.length:"+fieldsDest.length);for (int i = 0; i < fieldsDest.length; i++) {Field f = fieldsDest[i];Class type = f.getType();String name = f.getName();String typeName = type.getName();// logger.debug("[Time]::"+i+"[colname]:"+name+"[Typename]:"+typeName);if (name.equals("FIELDNUM") || name.equals("PK")|| name.equals("mErrors") || name.equals("fDate")) {continue;}for (int j = 0; j < fieldsOrg.length; j++) {// 得到数据源的数据Field f1 = fieldsOrg[j];// Class type1 = f1.getType();String name1 = f1.getName();String typeName1 = type.getName();// logger.debug("[times]:"+j+"[colname1]:"+name1+"[Typename1]:"+typeName1);// 取出冗余变量if (name.equals("FIELDNUM") || name.equals("PK")|| name.equals("mErrors") || name.equals("fDate")) {continue;}// 赋值转换if ((typeName.equals(typeName1)) && (name1.equals(name))) {switch (transType(typeName)) {case 3:try {f.setDouble(a, f1.getDouble(b));} catch (Exception e) {e.printStackTrace();}break;case 5:try {f.setInt(a, f1.getInt(b));} catch (Exception e) {e.printStackTrace();}break;case 93:try {f.set(a, f1.get(b));} catch (Exception e) {e.printStackTrace();}break;default:try {f.set(a, f1.get(b));// logger.debug("------Default:"+f1.get(b));} catch (Exception e) {e.printStackTrace();}break;}}}}return a;}


0 0
原创粉丝点击