反射还可以这样学?

概念

将类的各个组成部分封装为其他对象,这就是反射机制。

java反射是可以让我们在运行时,通过类的class对象动态获取类的属性、方法等内部信息的机制

java代码在计算机中的经过三个阶段

  • 第一个阶段:.java文件经过编译之后变成.class文件。也称源代码阶段
  • 第二个阶段:类加载器加载.class文件到内存中。也称class类对象阶段
  • 第三个阶段:创建对象。也称运行时阶段

在这里插入图片描述

反射实现借助的四个类

Class:类的对象
Constructor:类的构造方法
Field:类中的属性对象
Method:类中的方法对象

原理

java语言经过编译之后会生成一个.class对象,反射就是通过字节码文件找到某一个类、类中的方法以及属性等。

好处

1、可以在程序的运行过程中操作对象

2、可以解耦,提高程序的可扩展性

获取Class对象的方式

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象(对应第一阶段,Source源代码阶段)
  2. 类名.class:通过类名的属性class获取(对应第二阶段,Class类对象阶段)
  3. 对象.getClass():getClass()方法在Object对象中定义着(对应第三阶段,Runtime运行时阶段)
  • 结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次。即无论通过哪一种方式获取的class对象都是同一个

Class对象的功能

获取功能

  1. 获取成员变量们
    • Field[] getFields():获取所有public修饰的成员变量
    • Field getField(Stringname):获取指定的public修饰的成员变量
    • Field[] getDeclaredFields():获取所有的成员变量。不考虑修饰符
    • Field getDeclaredField(String name):获取指定的成员变量
  2. 获取构造方法们
    • Constructor<?>[] getConstructors():获取所有public修饰的构造方法
    • Constructor getConstructor(类<?>… parameterTypes):获取指定的public修饰的构造方法
    • Constructor<?>[] getDeclaredConstructors():获取所有的构造方法。不考虑修饰符
    • Constructor getDeclaredConstructor(类<?>… parameterTypes):获取指定的构造方法
  3. 获取成员方法们
    • Method[] getMethods():获取所有public修饰的成员方法
    • Method getMethod(String name, 类<?>… parameterTypes):获取指定的public修饰的成员方法
    • Method[] getDeclaredMethods():获取所有的成员方法。不考虑修饰符
    • Method getDeclaredMethod(String name, 类<?>… parameterTypes):获取指定的成员方法
  4. 获取类名
    • String getName()

Field对象的常用方法

  • 设置值:void set(Object obj, Object value)
  • 获取值:Object get(Object obj)
  • 忽略访问权限修饰的安全检查:setAccessible(true)

Constructor对象的常用方法

  • 创建对象:T newInstance(Object… initargs)
  • 如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance方法

Method对象的常用方法

  • 执行方法:Object invoke(Object obj, Object… args)
  • 获取方法名称:String getName()

代码示例

Person类对象

package com.reflect;

public class Person {
    private String name;
    private int age;

    public String a;
    protected String b;
    String c;
    private String d;


    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 food){
        System.out.println("吃东西。。。"+food);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
}

Class对象创建的三种方式

package com.reflect;


public class ReflectDemo01 {
    /*
    获取class对象的三种方式:
    1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象(对应第一阶段,Source源代码阶段)
    2. 类名.class:通过类名的属性class获取(对应第二阶段,Class类对象阶段)
    3. 对象.getClass():getClass()方法在Object对象中定义着(对应第三阶段,Runtime运行时阶段)
     */
    public static void main(String[] args) throws Exception {
        //1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象(对应第一阶段,Source源代码阶段)
        Class cla1 = Class.forName("com.reflect.Person");
        System.out.println(cla1);

        //2. 类名.class:通过类名的属性class获取(对应第二阶段,Class类对象阶段)
        Class cla2 = Person.class;
        System.out.println(cla2);

        //3. 对象.getClass():getClass()方法在Object对象中定义着(对应第三阶段,Runtime运行时阶段)
        Person p = new Person("Chocolate",24);
        Class cla3 = p.getClass();
        System.out.println(cla3);

        //结论:同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次。即无论通过哪一种方式获取的class对象都是同一个
        System.out.println(cla1==cla2);//true
        System.out.println(cla1==cla3);//true

    }
}

获取成员变量、成员方法、构造方法以及分别调用各自的方法

package com.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectDemo02 {

    public static void main(String[] args) throws Exception {
        //获取成员变量
        //demo01();
        
        //获取构造方法
        //demo02();
        
        //获取成员方法
        demo03();
    }

    private static void demo03() throws Exception {
        /*
         * Method[]  getMethods():获取所有public修饰的成员方法
         * Method getMethod(String name, 类<?>... parameterTypes):获取指定的public修饰的成员方法
         * Method[]  getDeclaredMethods():获取所有的成员方法。不考虑修饰符
         * Method getDeclaredMethod(String name, 类<?>... parameterTypes):获取指定的成员方法
         */
        Class cla = Class.forName("com.reflect.Person");
        //Method[]  getMethods():获取所有public修饰的成员方法
        Method[] methods = cla.getMethods();
        for (Method m:methods){
            System.out.println(m);
        }
        System.out.println("==============================");
        //Method getMethod(String name, 类<?>... parameterTypes):获取指定的public修饰的成员方法
        Person p = new Person();
        Method eat = cla.getMethod("eat");
        Method eat1 = cla.getMethod("eat", String.class);
        System.out.println(eat);
        System.out.println(eat1);
        //执行方法
        eat.invoke(p);
        eat1.invoke(p,"饭");
        System.out.println("============================");
        //获取方法名
        System.out.println(eat.getName());
        System.out.println("============================");
        //获取类名
        System.out.println(cla.getName());

    }

    private static void demo02() throws Exception {
        /*
           * Constructor<?>[] getConstructors():获取所有public修饰的构造方法
           * Constructor<T> getConstructor(类<?>... parameterTypes):获取指定的public修饰的构造方法
           * Constructor<?>[] getDeclaredConstructors():获取所有的构造方法。不考虑修饰符
           * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes):获取指定的构造方法
         */
        Class cla = Class.forName("com.reflect.Person");
        Constructor[] constructors = cla.getConstructors();
        for (Constructor c:constructors){
            System.out.println(c);
        }
        System.out.println("==========================");
        //获取指定的构造器
        Constructor cons = cla.getConstructor(String.class,int.class);
        System.out.println(cons);
        System.out.println("============================");
        //由构造器创建对象
        //创建对象:T   newInstance(Object... initargs)
        Object obj = cons.newInstance("科比", 24);
        System.out.println(obj);
        System.out.println("==========================");
        //如果使用空参构造方法创建对象,操作可以简化:Class对象的newInstance方法
        Object obj2 = cla.newInstance();
        System.out.println(obj2);
    }

    private static void demo01() throws Exception {
        /*
         * Field[]  getFields():获取所有public修饰的成员变量
         * Field  getField(Stringname):获取指定的public修饰的成员变量
         * Field[]  getDeclaredFields():获取所有的成员变量。不考虑修饰符
         * Field  getDeclaredField(String name):获取指定的成员变量
         */
        Class cla = Class.forName("com.reflect.Person");
        //getFields():获取所有public修饰的成员变量
        Field[] f1 = cla.getFields();
        for (Field f:f1){
            System.out.println(f);
        }
        System.out.println("===========================");
        //getDeclaredFields():获取所有的成员变量。不考虑修饰符
        Field[] f2 = cla.getDeclaredFields();
        for (Field f:f2){
            System.out.println(f);
        }
        System.out.println("===============================");
        //getField(Stringname):获取指定的public修饰的成员变量
        //获取某个成员变量,并对其进行赋值
        /*
        Field:成员变量
            * 设置值:void 	set(Object obj, Object value)
            * 获取值:Object    get(Object obj)
            * 忽略访问权限修饰的安全检查:setAccessible(true)
         */
        Person p = new Person();
        Field a = cla.getField("a");
        a.set(p,"我是a");
        Object o = a.get(p);
        System.out.println(o);
        System.out.println(p);


    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值