corejava 第十八天

反射

反射是java中提供的一种机制,它允许我们在程序运行的时候,动态获取一个类中的基本信息,并且可 以调用类中的属性、方法、构造器。

现实:物体------->镜面/水面------>返回原来的物体

java:.class------>jvm-------->ClassDefineInformation

Class类型

java.lang.Class 是API中提供的一个类,它可以表示java中所有的类型,包括基本类型和引用类型。

public final native Class getClass();

该方法的返回类型就是Class,所以 obj.getClass(); 这句代码的含义就是:返回obj引用在运行时所 指向对象的实际类型。

获取Class对象

在java中,每种类型(基本类型和引用类型)加载到内存之后,都会在内存中生成一个Class类型对象, 这个对象就代表这个具体的java类型,并且保存这个类型中的基本信息。

注意,java中的每种类型,都有且只有唯一的一个Class类型对象与之对应!并且在类加载的时候自动生成!

获取基本类型的Class对象:

只有一种方式: Class c = int.class;

获取接口类型的Class对象:

有俩种方式:

  • Class c1 = int[].class;
  • int[] arr = new int[4]; Class c2 = arr.getClass();

获取数组类型的Class对象:

有俩种方式:

  • Class c1 = int[].class;
  • int[] arr = new int[4]; Class c2 = arr.getClass();

获取类类型的Class对象:

有三种方式:

  • Class c1 = Student.class;
  • Class c2 = Class.forName(“com.briup.demo.Student”);
  • Student stu = new Student(); Class c3 = stu.getClass();

可以看出,获取一个类型Class对象的途径一般有三种

  • 使用类型名称直接获取
  • 使用Class类中的静态方法forName获取
  • 使用对象调用getClass方法获取

获取类的信息

类中有属性、方法、构造器 我们都可以获取;

  • Field :类的属性

    Field[] getFields()//获取所有属性

    Field getField(String name)//获取指定name的属性

    Field[] getDeclaredFields()//获取所有声明的属性 包括私有的

    Field getDeclaredField(String name)//获取指定name的属性 可以是私有的

        Class c = Class.forName("Student");
        Field[] fields = c.getDeclaredFields();
    	for(Field f : fields){
            System.out.println("属性的修饰符:"+Modifier.toString(f.getModifiers()));
            System.out.println("属性的类型:"+f.getType().getName());
            System.out.println("属性的名称:"+f.getName());
            System.out.println("---------------------");
          }
    
  • Method:类的方法

    获取当前类中的public方法,包含从父类中继承的public方法

    Method[] getMethods()

    Method getMethod(String name, Class… parameterTypes)

    获取当前类中声明的方法(包含私有的),但是不能获取从父类中继承过来的方法

    Method[] getDeclaredMethods()

    Method getDeclaredMethod(String name, Class… parameterTypes)

     public static void main(String[] args) throws Exception {
            Student stu = new Student();
            Class c = stu.getClass();
            //获取类中声明的所有方法
            Method[] methods = c.getDeclaredMethods();
            for (Method m : methods) {
                //获取方法的修饰符
                System.out.println(Modifier.toString(m.getModifiers()));
                //获取方法的返回类型
                System.out.println(m.getReturnType().getSimpleName());
                //获取方法的名字
                System.out.println(m.getName());
                System.out.println("方法参数个数:" + m.getParameterCount());
                //获取方法的参数列表
                Class[] paramArr = m.getParameterTypes();
                //输出方法的参数列表
                System.out.println("\t" + Arrays.toString(paramArr));
                //获取方法所抛出的异常类型
                Class[] exceptionArr = m.getExceptionTypes();
                System.out.println("方法抛出异常个数:" + exceptionArr.length);
    			//输出方法所抛出的异常列表
                System.out.println("\t" + Arrays.toString(exceptionArr));
                System.out.println("-------------------------------");
            }
        }
    
  • Constructor:类的构造器

    获取当前类中的public构造器

    public Constructor[] getConstructors()

    public Constructor getConstructor(Class… parameterTypes)

    获取当前类中的所有构造器,包含私有的

    public Constructor[] getDeclaredConstructors()

    public Constructor getDeclaredConstructor(Class… parameterTypes)

        public static void main(String[] args) throws Exception {
            Student stu = new Student();
            Class c = stu.getClass();
    		//获取类中所有的public构造器
            Constructor[] constructors = c.getConstructors();
            for (Constructor constructor : constructors) {
    		//构造器的修饰符
                System.out.println(Modifier.toString(constructor.getModifiers()));
    		//构造器的名字
                System.out.println(constructor.getName());
    		//构造器的参数列表
                Class[] paramList = constructor.getParameterTypes();
                System.out.println(java.util.Arrays.toString(paramList));
    		//构造器的抛出异常
                Class[] exceptionList = constructor.getExceptionTypes();
                System.out.println(java.util.Arrays.toString(exceptionList));
                System.out.println("-----------------------------");
            }
        }
    

访问属性

    public static void main(String[] args) throws Exception {
        Student stu = new Student();
        Class c = stu.getClass();
//获取类中名字叫name的属性
        Field f1 = c.getDeclaredField("name");
//设置私有属性可以被访问,否则报错
        f1.setAccessible(true);
//用反射的方式,给指定对象的name属性赋值
//相当于之前的stu.name = "tom";
        f1.set(stu, "tom");
//用反射的方式,获取这个属性的值
//相当于之前的stu.name
        System.out.println(f1.get(stu));
        System.out.println("----------------------");
//获取类中名字叫age的属性
        Field f2 = c.getDeclaredField("age");
//用反射的方式,给指定对象的age属性赋值
//相当于之前的stu.age = 20;
        f2.set(stu, 20);
//用反射的方式,获取这个属性的值
//相当于之前的stu.age
        System.out.println(f2.get(stu));
        System.out.println("----------------------");
//获取类中名字叫num的属性
        Field f3 = c.getDeclaredField("num");
//用反射的方式,给静态属性num赋值,不需要对象
//相当于之前的Student.num = 99;
        f3.set(null, 99);
//用反射的方式,获取这个静态属性的值,不需要对象
//相当于之前的Student.num
        System.out.println(f3.get(null));
    }

访问方法

    public static void main(String[] args) throws Exception {
        Student stu = new Student();
        Class c = stu.getClass();
        //获取类中的toString方法,没有参数,这是从父类继承的方法
        Method m1 = c.getMethod("toString", null);
        //反射的方式,调用stu对象中的这个方法,没有参数,并接收执行结果
        //相当于之前的:Object result = stu.toString();
        Object result = m1.invoke(stu, null);
        //输出执行结果
        System.out.println(result);
        System.out.println("-------------------");
        //获取类中的sayHello方法,需要一个String类型的参数,这是自己定义的方法
        Method m2 = c.getMethod("sayHello", String.class);
        //反射的方式,调用stu对象中的这个方法,参数是"tom",并接收执行结果
        //相当于之前的:Object result = stu.sayHello("tom");
        result = m2.invoke(stu, "tom");
        //输出执行结果
        System.out.println(result);
    }

通过反射创建对象(访问构造器)

使用反射的方式可以创建对象,也就是需要反射调用构造器。

例如,反射调用类中无参构造器创建对象

     public static void main(String[] args)throws Exception {
        Class c = Student.class;
        //默认调用类中的无参构造器来创建对象
        //相当于之前的:Object obj = new Student();
        Object obj = c.newInstance();
        System.out.println(obj);
    }

例如,反射调用类中有参构造器创建对象

    public static void main(String[] args)throws Exception {
        Class c = Student.class;
        //获取类中的俩参构造器
        Constructor constructor = c.getConstructor(String.class, int.class);
        //调用有参构造器创建对象,并传入对应的参数值
        //相当于之前的:Object obj = new Student("tom",20);
        Object obj = constructor.newInstance("tom",20);
        System.out.println(obj);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值