Java反射机制

  本文根据黑马课程总结总结而成。

反射机制的理解

  Reflection允许以编程方式访问有关已加载类的字段,方法和构造函数的信息,以及使用反射字段,方法和构造函数在封装和安全限制内对其底层对应项进行操作。

  简单地解释:反射就是加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

  1. 反射第一步:加载类,获取类的字节码:Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法:Method对象

第一步:加载类,获取Class对象

  • Class c1 = 类名.class

  • 调用Class提供方法:public static Class forName(String package);

  • Object提供的方法:public Class getClass(); Class c3 = 对象.getClass();

    // 第一种
    Class c1 = Student.class;
    System.out.println(c1.getName());
    // 第二种
    Class c2 = Class.forName("org.example.reflect.Student");
    // 第三种
    Student s = new Student();
    Class c3 = s.getClass();
    

第二步:获取类的构造器

  • Constructor<?>[] getConstructors() // 获取全部构造器(只能获取public修饰的)

  • Constructor<?>[] getDeclaredConstructors() // 获取全部构造器(只要存在就能拿到)

  • Constructor<?>[] getConstructor(Class<?> … parameterTypes) // 获取某个构造器(只能获取public修饰的)

  • Constructor<?>[] getDeclaredConstructor(Class<?> … parameterTypes) // 获取某个构造器(只要存在就能拿到)

    // Cat.java
    class Cat{
        private String name;
        private int age;
        public Cat(){
            
        }
        public Cat(String name, int age){
            this.name = name;
            this.age = age;
        }
        public void run(){
            System.out.println("猫跑的很快!");
        }
        public String eat(String name){
            return "猫在吃" + 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;
        }
    }
    // TestConstructor.java
    public void testGetConstructors(){
        // 1.反射第一步:必须先得到这个类的Class对象
        Class c = Cat.class;
        // 2.获取类的全部构造器(只能是public方法)
        Constructor[] constructors = c.getConstructors();
        // 2.获取类的全部构造器,无论什么方法进行修饰
        Constructor[] constructors = c.getDeclaredConstructors();
        // 3.遍历数组中每个构造器对象
        for(Constructor constructor: constructors){
            System.out.println(constructor.getName() + "----->" + constructor.getParameterCount());
        }
    }
    public void testGetConstructor() throws Exception{
        Class c = Cat.class;
        // 获取单个无参构造器(只能是public修饰的)
        Constructor constructor = c.getConstructor();
        // 获取单个无参构造器(什么修饰的都可以)
        Constructor constructor = c.getDeclaredConstructor();
        // 获取有参构造器
        Constructor constructor2 = c.getConstructor(String.class, int.class);
        // 获取有参构造器
        Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
    }
    

    获取类构造器的作用:初始化对象返回

    Class c = Cat.class;
    Constructor constructor1 = c.getDeclaredConstructor();
    Cat cat = (Cat) constructor1.newInstance();
    // 由于getDeclaredConstructor()可以获取private修饰的构造器,而private构造器是不允许外界访问的,所以会出现IllegalAccessException。
    // 可以这样修改
    constructor1.setAccessible(true); // 禁止检查访问权限
    Cat cat = (Cat) constructor1.newInstance();
    // 调用有参数构造器初始化对象
    Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
    constructor2.setAccessible(true);
    Cat cat2 = (Cat) constructor2.newInstance("hhh", 3);
    

第三步:获取类的成员变量

  • public Field[] getFields() // 只能获取public修饰的

  • public Field[] getDeclaredFields() // 无论什么修饰,都可以获取到

  • public Field getField(String name) // 获取某个public修饰的成员变量

  • public Field getDeclaredField(String name) // 无论什么修饰,都可以获取到

    // 获取类的全部成员变量
    Field[] fields = c.getDeclaredFields();
    // 定义某个成员变量
    Field fName = c.getDeclaredField("name");
    System.out.println(fName.getName() + "--->" + fName.getType());
    

    获取类的成员变量作用:赋值和取值

    // 赋值
    Cat cat = new Cat();
    fName.setAccessible(true);   // 因为name使用的是private修饰的,所以必须设置禁止查看访问权限
    fName.set(cat, "图图");
    // 取值
    String name = (String) fName.get(cat);
    

第四步:获取类的Method方法

  • Method[] getMethods // 获取全部方法(只能是pubic修饰的)

  • Method[] getDeclaredMethods // 同上,但是只要存在就能拿到

  • Method getMethod(String name, Class<?> … parameterTypes) // 获取某个成员方法,只能是public修饰的

  • Method getDeclaredMethod(String name, Class<?> … parameterTypes) // 获取某个成员方法,只要存在就能拿到

    Class c = Cat.class;
    Method[] method = c.getDeclaredMethods();
    for(Method method: methods){
        System.out.println(method.getName() + "---->"
                          + method.getParameterCount() + "---->"
                          + method.getReturnType());
    }
    // 获取某个方法对象
    Method run = c.getDeclaredMethod("run"); // 没有参数
    Method eat = c.getDeclaredMethod("eat", String.class);
    

    获取成员方法的作用:执行成员方法

    // 执行成员方法
    // public Object invoke(Object obj, Object … args)
    // public void setAccessible(boolean flag)
    Cat cat = new Cat();
    run.setccessible(true);  // 如果run方法是私有的,需要加上该语句
    Object rs = run.invoke(cat);	// 用cat对象调用无参的构造方法
    run.setccessible(true);  // 如果eat方法是私有的,需要加上该语句
    String rs2 = (String) eat.invoke(cat, "fish");
    

反射作用

  • 基本作用:可以得到一个类得全部成分然后对其进行操作;
  • 可以破坏封装性:可以访问私有构造器
  • 最重要的用途:适合做java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能模块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值