JavaSE(2)08 反射机制--获取运行时类的完整结构

反射机制

获取运行时类的完整结构

  • 通过反射获取运行时类的完整结构包括:Field、Method、Construct、SupperClass、interface、Annotation
  • 类的默认无参构造是私有的,用private修饰
//获得类的信息
public class Demo08 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.phx.reflection.Users");
        System.out.println(c1);//class com.phx.reflection.Users
        //获取类的名字
        System.out.println(c1.getName());//com.phx.reflection.Users  包名+类名
        System.out.println(c1.getSimpleName());//Users
        //获得类的属性
           //所有公共属性  getFields()
        Field[] fields = c1.getFields();
        for (Field field : fields) {
            System.out.println(field);//public int com.phx.reflection.Users.age
        }
        System.out.println();
           //所有属性:公有+私有 getDeclaredFields()
        Field[] declaredFields = c1.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);  //private java.lang.String com.phx.reflection.Users.name
                                                //private java.lang.String com.phx.reflection.Users.sex
                                                //public int com.phx.reflection.Users.age

        }
          //通过属性名获取单个公有属性 getField() 如果获取私有属性和不存在属性会报错 java.lang.NoSuchFieldException
        Field age = c1.getField("age");
        System.out.println(age);//public int com.phx.reflection.Users.age
         //通过属性名获取单个公有/私有 属性 getDeclaredField()
        Field name = c1.getDeclaredField("name");
        System.out.println(name);//java.lang.String com.phx.reflection.Users.name
        System.out.println("===============");
        //获取类的方法
            //获取所有方法:getMethods(),获取当前类及父类的所有公共方法
        Method[] methods = c1.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        System.out.println("===============");
            //获取所有方法:getDeclaredMethods(),获取当前类所有公共方法 + 所有私有方法
        Method[] declaredMethods = c1.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        System.out.println("===============");
            //获取指定公有方法:getMethod("方法名","方法返回值类型.class(void时用null)")如果没有该方法或该方法的返回值类型和实际返回值类型不匹配或该方法是私有的报异常:java.lang.NoSuchMethodException
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(setName);
           //获取指定方法(公有/私有):getDeclaredMethod ("方法名","方法返回值类型.class(void时用null)")如果没有该方法或该方法的返回值类型和实际返回值类型不匹配报异常:java.lang.NoSuchMethodException
        Method getName = c1.getDeclaredMethod("getName", null);
        System.out.println(getName);
        Method sayHello = c1.getDeclaredMethod("sayHello", String.class);
        System.out.println(sayHello);
        System.out.println("===============");
        //获取类的构造器
        //getConstructors():获取所有公有的构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);//public com.phx.reflection.Users(java.lang.String,java.lang.String,int)
        }
        //getDeclaredConstructors():获取所有构造器(公有+私有)  注意:类的默认无参构造是私有的,用private修饰
        Constructor[] declaredConstructors = c1.getDeclaredConstructors();
        for (Constructor declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);//private com.phx.reflection.Users()
                                                    //public com.phx.reflection.Users(java.lang.String,java.lang.String,int)
        }
        //获取指定构造器
        //getConstructor("参数类型.class"):获取指定的公有构造器
        Constructor constructor = c1.getConstructor(String.class, String.class, int.class);
        System.out.println(constructor);//public com.phx.reflection.Users(java.lang.String,java.lang.String,int)
        //getDeclaredConstructor("参数类型.class"):获取指定的公有/私有构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(null);
        System.out.println(declaredConstructor);//private com.phx.reflection.Users()
    }
}
class Users{
    private Users(){}
    public Users(String name,String sex,int age){
        this.name=name;
        this.sex=sex;
        this.age=age;

    }
    private String name="张三";
    private String sex="男";
    public int age=20;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    private void sayHello(String name){
        System.out.println("Hello"+name);
    }
}

调用运行时类的指定结构

  • 创建类的对象:调用Class对象的newInstance()方法
    • 必须要有一个无参的构造器
    • 类的构造器的访问权限需要足够
    • 如果是有参构造
      1、通过getConstructor(Class<?>… parameterTypes)取得本类的指定形参类型的构造器
      2、向构造器形参中传递一个对象数组进去,里面包含了构造器所需的各个参数
      3、通过Constructor实例化对象
  • 调用指定的方法
    • 通过Class类的getMethod(String name, Class<?>… parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的的参数类型
    • 之后调用Object invoke(Object obj, Object… args) 进行调用,并向方法传递要设置的ojb对象的参数信息
  • Object invoke(Object obj, Object… args)
    • Object 对应原方法的返回值,若原方法没有返回值怎返回null
    • 若原方法为静态方法,此时形参Object obj可为null
    • 若原方法形参列表为空,则Object[] args为null
    • 若原方法声明为private,则需要在调用此invoke()方法前,显示调用方法对象的setAccessible(true)方法,将可访问private的方法
  • setAccessible
    • Method和Field、Constructor对象都有setAccessible()方法
    • setAccessible的作用是 启动和禁用访问安全检查的开关
    • 参数为true表示反射的对象在使用时取消了Java语言的访问检查,关闭后可以提高反射效率,可以访问原本无法访问的私有成员
//动态的创建对象,通过反射
public class Demo09 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.phx.reflection.Users");
        //构造一个对象
        Users users = (Users) c1.newInstance();//如果该类有有参构造而没有创建无参构造则报异常java.lang.NoSuchMethodException: com.phx.reflection.Users.<init>()
        System.out.println(users);//Users{name='null', sex='null', age=0}
        //通过构造器创建对象
        Constructor constructor = c1.getConstructor(String.class, String.class, int.class);
        Users users2 = (Users) constructor.newInstance("zs","男",18);
        System.out.println(users2);//Users{name='zs', sex='男', age=18}
        //通过反射调用普通方法 不能直接操作私有方法/属性,需要关闭程序的权限检,属性/方法的setAccessible(true)关闭
        //invoke(“对象”,“方法中的参数值”):激活
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.invoke(users2,"ls");
        Method getName = c1.getMethod("getName");
        System.out.println(getName.invoke(users2));//ls
        Method sayHello = c1.getDeclaredMethod("sayHello", String.class);
        sayHello.setAccessible(true);// 关闭权限检查 如果是private修饰的属性或方法不关闭权限加测会报错 java.lang.IllegalAccessException:
        sayHello.invoke(users2,"zs");//Hellozs
        //通过反射操作属性
        Field name = c1.getDeclaredField("name");
        name.setAccessible(true);//如果是private修饰的属性或方法不关闭权限加测会报错 java.lang.IllegalAccessException:
        name.set(users,"ww");//给users对象的name属性赋值
        Method getName2 = c1.getMethod("getName");
        System.out.println(getName2.invoke(users));//ww  调用users对象的getName方法
    }
}
  • 性能对比分析
//分析性能问题
@SuppressWarnings("all")
public class Demo10 {
    //普通方式调用
    public static void test01(){
        Users users=new Users();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000000000; i++) {
            users.getName();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("普通方式调用10亿次调用耗时:"+(endTime-startTime)+"ms");
    }
    //反射方式调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Users users=new Users();
        long startTime = System.currentTimeMillis();
        Method getName = users.getClass().getMethod("getName");
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(users);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式调用10亿次调用耗时:"+(endTime-startTime)+"ms");
    }
    //反射方式调用 关闭安全检查
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Users users=new Users();
        long startTime = System.currentTimeMillis();
        Method getName = users.getClass().getMethod("getName");
        getName.setAccessible(true);
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(users);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("反射方式关闭安全检查调用10亿次调用耗时:"+(endTime-startTime)+"ms");
    }
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();//普通方式调用10亿次调用耗时:4ms
        test02();//反射方式调用10亿次调用耗时:3877ms
        test03();//反射方式关闭安全检查调用10亿次调用耗时:1872ms
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值