java基础之反射

来源:互联网 发布:安卓按键软件 编辑:程序博客网 时间:2024/05/16 14:41

java数据类型都有一个相应的Class对应。

对象是表示或封装一些数据。一个类被加载后,JVM会创建一个对应该类的Class对象,类的整个结构信息会放到对应的Class对象中。这个Class对象就像一面镜子一样,通过这面镜子我可以看到对应类的全部信息。
            String path = "com.test.user";            Class clazz = Class.forName(path);            System.out.println(clazz.hashCode());            Class clazz2 = Class.forName(path); //一个类只对应一个Class对象            System.out.println(clazz2.hashCode());            Class strClazz = String.class;            Class strClazz2 = path.getClass();             System.out.println(strClazz==strClazz2);

两次hashcode相等,strClazz 等于strClazz 2,故java数据类型都只对应一个相应的Class对象。
对于数组而言,数组元素类型与维度一样,则对应的Class一样。

获取类的属性、方法和构造器

属性:

            Field[] fields = clazz.getFields(); //只能获得public的field            Field[] fields = clazz.getDeclaredFields();//获得所有的field            Field f = clazz.getDeclaredField("uname");

加了Declared的方法都是获取的所有的,没加的只能获取public修饰的。

方法:

            Method[] methods = clazz.getDeclaredMethods();            Method m01 = clazz.getDeclaredMethod("getUname", null);

构造器:

            Constructor[] constructors = clazz.getDeclaredConstructors();            Constructor c = clazz.getDeclaredConstructor(int.class,int.class,String.class);

生成对象,操作方法属性

生成对象

            Class<User> clazz = (Class<User>) Class.forName(path);            //通过反射API调用构造方法,构造对象            User u = clazz.newInstance();   //其实是调用了User的无参构造方法            Constructor<User> c = clazz.getDeclaredConstructor(int.class,int.class,String.class);            User u2 = c.newInstance(1001,18,"张三");

调用普通方法

User u3 = clazz.newInstance();            Method method = clazz.getDeclaredMethod("setUname", String.class);            method.invoke(u3, "张三");   //u3.setUname("张三");

操作属性

            User u4 = clazz.newInstance();            Field f = clazz.getDeclaredField("uname");            f.setAccessible(true); //这个属性不需要做安全检查了,可以直接访问            f.set(u4, "李四");        //通过反射直接写属性

通过反射获取泛型信息

public class Demo04 {    public void test01(Map<String,User> map,List<User> list){        System.out.println("Demo04.test01()");    }    public Map<Integer,User> test02(){        System.out.println("Demo04.test02()");        return null;    }    public static void main(String[] args) {        try {            //获得指定方法参数泛型信息            Method m = Demo04.class.getMethod("test01", Map.class,List.class);            Type[] t = m.getGenericParameterTypes();            for (Type paramType : t) {                System.out.println("#"+paramType);                if(paramType instanceof ParameterizedType){                    Type[] genericTypes = ((ParameterizedType) paramType).getActualTypeArguments();                    for (Type genericType : genericTypes) {                        System.out.println("泛型类型:"+genericType);                    }                }            }            //获得指定方法返回值泛型信息            Method m2 = Demo04.class.getMethod("test02", null);            Type returnType = m2.getGenericReturnType();            if(returnType instanceof ParameterizedType){                    Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();                    for (Type genericType : genericTypes) {                        System.out.println("返回值,泛型类型:"+genericType);                    }            }        } catch (Exception e) {            e.printStackTrace();        }    }}

结果:

#java.util.Map<java.lang.String, com.test.bean.User>泛型类型:class java.lang.String泛型类型:class com.test.bean.User#java.util.List<com.test.bean.User>泛型类型:class com.test.bean.User返回值,泛型类型:class java.lang.Integer返回值,泛型类型:class com.test.bean.User

三种执行方法的效率差异比较

public class Demo5 {    public static void test01(){        User u = new User();        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000L; i++) {            u.getUname();        }        long endTime = System.currentTimeMillis();        System.out.println("普通方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");     }    public static void test02() throws Exception{        User u = new User();        Class clazz = u.getClass();        Method m = clazz.getDeclaredMethod("getUname", null);//      m.setAccessible(true);        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000L; i++) {            m.invoke(u, null);        }        long endTime = System.currentTimeMillis();        System.out.println("反射动态方法调用,执行10亿次,耗时:"+(endTime-startTime)+"ms");    }    public static void test03() throws Exception{        User u = new User();        Class clazz = u.getClass();        Method m = clazz.getDeclaredMethod("getUname", null);        m.setAccessible(true);  //不需要执行访问安全检查        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000L; i++) {            m.invoke(u, null);        }        long endTime = System.currentTimeMillis();        System.out.println("反射动态方法调用,跳过安全检查,执行10亿次,耗时:"+(endTime-startTime)+"ms");    }    public static void main(String[] args) throws Exception {        test01();        test02();        test03();    }}

结果:

普通方法调用,执行10亿次,耗时:301ms反射动态方法调用,执行10亿次,耗时:1546ms反射动态方法调用,跳过安全检查,执行10亿次,耗时:911ms
1 0