java基础之反射

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值