反射

反射

反射库提供了的工具集可以用来编写能够动态操作Java代码的程序,使用反射,Java可以支持用户界面生成器、对象关系映射器以及很多其他需要动态查询能力的开发工具。

能够分析类能力的程序称为反射。

反射机制可以用来:

  1. 在运行时分析类的能力。
  2. 在运行时检查对象,例如,编写一个适用于所有类的toString方法。
  3. 实现泛型数组操作代码。
  4. 利用Method对象,这个对象很像C++中的指针。

Class类

在程序运行期间,Java运行时系统始终为所有对象维护一个运行时类型标识。这个信息会跟踪每个对象所属的类。虚拟机利用运行时类型信息选择要执行的正确方法。

可以使用一个特殊的Java类访问这些信息,保存这些信息的类名为Class。Class对象会描述一个特定类的属性。

获取Class对象的方式

  1. 静态方法Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象。

    多用于配置文件,将类名定义在配置文件中。读取文件,加载类。

    可通过调用Class.forName手工强制加载类。

    String className = "java.util.Random";
    Class cl = Class.forName(className);
    

    如果类名保存在一个字符串中,这个字符串会在运行时变化,就可以使用这个方法。如果className是一个类名或接口名,这个方法可以正常运行,否则forName方法将抛出一个检查型异常。使用这个方法应该提供一个异常处理器。

  2. 类名.Class:通过类名的属性class获取。

    多用于参数传递。

    如果T是任意Java类型(或void关键字),T.class将代表匹配的类对象。

    Class cl1 = Random.class;
    Class cl2 = int.class;
    Class cl3 = Double[].class;
    

    一个Class对象实际上表示的是一个类型,这可能是类,也可能不是类。例如int不是类,但int.class是一个Class类型的对象。

  3. 对象.getClass():返回一个Class类型的实例。此方法在Object类中。

    多用于对象的获取字节码的方式。

    Employee e;
    Class cl = e.getClass();
    

Class对象功能

获取功能

1. 获取成员变量
  • Field[] getFields()

    获取public修饰的成员变量并返回包含这些Field对象的数组,这些对象对应这个类或其超类的公共字段。

  • Field getField(String name)

    获取指定名称的public修饰成员变量返回Field对象

  • Field[] getDeclaredFields()

    获取本类所有成员变量并返回包含这些Field对象的数组,这些对象对应这个类的全部字段。如果类中没有字段,或者Class对象描述的是基本类型或数组类型,这些方法将返回一个长度为0的数组。

  • Field getDeclaredField(String name)

    获取指定名称的成员变量并返回Field对象

操作操作成员变量
  • 获取值:get(Object obj)

  • 设置值:void set(object obj,Object value)

  • 忽略访问权限修饰符的安全检查:setAccessible(true) 暴力反射

public class Person {
    private String name;
    protected int age;
    int id;
    public int score;

    public Person() {
    }

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

    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;
    }

    public void eat(){
        System.out.println("吃饭");
    }

    public void eat(String name){
        System.out.println(name+"吃饭");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", id=" + id +
                ", score=" + score +
                '}';
    }
}
import java.lang.reflect.Field;

public class ReflectDamo01 {
    public static void main(String[] args) throws Exception {
        Class pc = Person.class;

        //获取成员变量
        Field[] fields = pc.getFields();
        for (Field f : fields) {
            System.out.println(f);
        }//这个方法只能获取到公共变量score

        Field[] declearedFields = pc.getDeclaredFields();
        for (Field e : declearedFields) {
            System.out.println(e);
        }//获取本类所有成员变量

        Field field = pc.getField("score");
        //获取成员变量score的值
        Person p = new Person();
        Object value = field.get(p);
        System.out.println(value);
        //设置成员变量score的值
        field.set(p,100);
        System.out.println(p);

        Field name = pc.getDeclaredField("name");
        //忽略访问权限修饰符的安全检查
        name.setAccessible(true);//暴力反射
        Object v2 = name.get(p);
        System.out.println(v2);

    }
}
2. 获取构造方法
  • Constructor[] getConstructors()

    返回包含一个数组 Constructor对象反射由此表示的类的所有public公共构造 对象。

  • Constructor getConstructor(类… parameterTypes)

    返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的public公共 函数。

  • Constructor[] getDeclaredConstructors()

    返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组

  • Constructor getDeclaredConstructor(类… parameterTypes)

    返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 函数。

创建对象
  • T newInstance(Object… initargs)

    使用此 Constructor对象表示的构造函数,使用指定的初始化参数来创建和初始化构造函数的声明类的新实例

  • T newInstance()

    创建由此 对象表示的类的新实例。

import java.lang.reflect.Constructor;

public class ReflectDamo02 {
    public static void main(String[] args) throws Exception {
        Class pc = Person.class;

    //获取有参构造器class对象
    Constructor constructor = pc.getConstructor(String.class, int.class);
    System.out.println(constructor);
    //创建对象
    Object obj = constructor.newInstance("小明",15);
    System.out.println(obj);

    //使用空参构造器创建对象可以使用class对象的newInstance方法
    Object o = pc.newInstance();
    System.out.println(o);

    //constructor.setAccessible(true); 暴力反射

  }
}
3. 获取成员方法
  • Method[] getMethods()

    返回包含一个数组 方法对象反射由此表示的类或接口的所有public公共方法 对象,包括那些由类或接口和那些从超类和超接口继承的声明。

  • Method getMethod(String name, 类… parameterTypes)

    返回一个 方法对象,它反映此表示的类或接口的指定public公共成员方法 对象。

  • Method[] getDeclaredMethods()

    返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 对象,包括公共,保护,默认(包)访问和私有方法,但不包括由超类继承的方法。

  • Method getDeclaredMethod(String name, 类… parameterTypes)

    返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 对象。

执行方法
  • Object invoke(Object obj, Object… args)

    在具有指定参数的方法对象上调用此方法对象表示的底层方法。

  • 获取方法名:String getName()

import java.lang.reflect.Method;

public class ReflectDamo03 {
    public static void main(String[] args) throws Exception {
        Class pc = Person.class;

        //获取指定名称的方法对象
        Method eatMethod = pc.getMethod("eat");
        //执行空参方法
        Person p = new Person();
        eatMethod.invoke(p);
        
        //执行有参方法
        Method method = pc.getMethod("eat", String.class);
        method.invoke(p,"小明");
        //获取方法名
        String name = method.getName();
        System.out.println(name);

        //获取所有超类(Object类)和子类的public方法
        Method[] methods = pc.getMethods();
        for (Method m : methods) {
            System.out.println(m);
        }

        //method.setAccessible(true);暴力反射
    }
}
4. 获取类名
  • String getName()

    返回由 对象表示的实体(类,接口,数组类,原始类型或空白)的名称,作为 String

String classname = pc.getName();
System.out.println(classname);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值