初识反射

初识反射

通过反射可以获取类的Class对象, 一个类在内存中只有一个Class对象,Class对象不能开发者自己创建, 只能获取, 一个类被加载后类的整个结构都将被封装在Class对象中

获得Class对象的几种方法

public class GetClass {
    public static void main(String[] args) throws ClassNotFoundException {
        
        //1.通过 对象.getClass() 获得
        Teacher william = new Teacher("william");
        Class c1 = william.getClass();
        System.out.println(c1);
        System.out.println("c1.hashCode() = " + c1.hashCode());

        //2.Class.forName(String className) 获得
        Class c2 = Class.forName("com.cqu.william.AnnotationAndReflection.Student");
        System.out.println("c2.hashCode() = " + c2.hashCode());

        //3.通过 类名.class 获得
        Class c3 = Student.class;
        System.out.println(c3);
        System.out.println("c3.hashCode() = " + c3.hashCode());  //同一个类的Class的hashcode相同

        //4.基本内置类型的包装类都有一个TYPE属性
        Class<Integer> c4 = Integer.TYPE;
        System.out.println("c4 = " + c4);

        //5.通过Class.getSuperclass()可以获得其父类的Class对象
        Class c5 = c2.getSuperclass();
        System.out.println("c5 = " + c5);
    }
}

class Person {
    public String name;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }
}

class Student extends Person {
    public Student(String name) {
        super(name);
    }
}

class Teacher extends Person {
    public Teacher(String name) {
        super(name);
    }
}

Class.getxxx()

public class GetName {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");

        //获得类的名字
        System.out.println("c1.getName() = " + c1.getName());//获得包名+类名
        System.out.println("c1.getSimpleName() = " + c1.getSimpleName());//获得类名

        //获得类的属性
        Field[] fields = c1.getFields(); //只能获得public属性的数组
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("======================================");

        fields = c1.getDeclaredFields(); //获得所有属性的数组
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("======================================");

        Field name = c1.getDeclaredField("name");
        System.out.println(name);//获得指定属性
        System.out.println("======================================");

        //  获得方法
        Method[] methods = c1.getMethods();//获得本类及父类的所有public方法的数组
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("======================================");


        Field[] declaredFields = c1.getDeclaredFields();//获得本类的所有方法的数组
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        System.out.println("======================================");

        //获得所有public构造器的数组
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("======================================");

        //获得所有public构造器的数组
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
    }
}

动态创造对象

public class Dyn {
    private static Object william;

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        
        Class c1 = Class.forName("com.cqu.william.AnnotationAndReflection.User");

        //使用newInstance()动态构造对象
        User user = (User) c1.newInstance();
        System.out.println(user);

        //使用getDeclaredConstructor(params)获取构造器, 通过构造器创建对象
        Constructor c = c1.getDeclaredConstructor(String.class, int.class, int.class);
        Object william = c.newInstance("william", 20193818, 19);

        //使用getDeclaredMethod()获取指定方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //使用invoke调用william对象的setName方法,参数为"ABC"
        setName.invoke(william, "ABC");

        //使用getDeclaredField()获得字段
        Field name = c1.getDeclaredField("name");
        //setAccessible(true)关闭反射的检测
        name.setAccessible(true);
        name.set(william, "william");
    }
}

反射的执行表现

反射使得执行效率大大降低, 通过关闭检测setAccessible(true)能稍微提升

// 分别使用三种方式执行10亿次循环, 记录所用的时间, 比较执行效率

public class Performance {
    public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        test01();
        test02();
        test03();
    }

    //普通方式调用getName()
    static void test01() {
        User user = new User();

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("普通方式执行循环体10亿次 " + (endTime - startTime) + "ms");
    }

    //反射方式调用getName()
    static void test02() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        User user = new User();
        //通过getClass()得到user的Class对象
        Class c1 = user.getClass();
        // getDeclaredMethod("getName")得到User.getName()方法
        Method getName = c1.getDeclaredMethod("getName");

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            // getName.invoke(user)表示对user对象使用getName方法
            getName.invoke(user);
        }
        long endTime = System.currentTimeMillis();

        System.out.println("反射方式执行循环体10亿次 " + (endTime - startTime) + "ms");
    }


    //反射方式调用getName()并关闭检测
    static void test03() throws NoSuchMethodException {
        User user = new User();
        Class c3 = user.getClass();
        Method getName = c3.getDeclaredMethod("getName");

        //setAccessible(true)关闭检测
        getName.setAccessible(true);

        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
        long endTime = System.currentTimeMillis();

        System.out.println("关闭检测执行循环体10亿次 " + (endTime - startTime) + "ms");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值