Java反射基础小入门(学习笔记)

首先,认识一下Java代码 在计算机中经历的阶段 (三个阶段)

在这里插入图片描述

反射:将类的各个组成部分封装为其他对象

好处:

  1. 在程序运行中,拿到这些对象
  2. 可以解耦,提高程序的可扩展性

获取Class对象的方式:

 1. 通过类型获得
  // 语法:类名.class
  // 应用场景:确定类型等
    Class beansClass = 类名.class;
   
 2 通过实例对象获得
    // 语法:变量.getClass()
    // 应用场景:在方法内部通过参数获得类型等 
    // 先给你 new一个对象
    Beans beans = new Beans();
    Class<? extends Beans> aClass = beans.getClass();

 3 通过字符串获得
    // 语法:Class.forName("全限定类名")
    // 应用场景:通过配置获得字符串等
    Class<?> aClass1 = Class.forName("Demo01.Beans");

同一个字节码文件(*.Class)再一次程序运行过程中,只会内加载一次 无论哪一种方式获取Class对象都是同一个

Class对象功能:

获取功能:

  1. 获取成员变量

    Field[] getFields()

    Field getField(String name)

    Field[] getDeclaredFields( )

    Field getDeclaredField(String name)

  2. 获取构造方法

    Constructor<?> getConstructors()

    Constructor<T> getConstructor(类<?>... parameterTypes)

    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

    Constructor<?>[] getDeclaredConstructors()

  3. 获取成员方法

    Method getMethods()
    Method getMethod(String name, 类<?>... parameterTypes)

    Method[] getDeclaredMethods()
    Method getDeclaredMethod(String name, 类<?>... parameterTypes)

  4. 获取类名

    String getName()

功能演示:(获取成员变量)

Person类:

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

    public Person() {
    }

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }
}

Field[] getFields() 获取所有的成员变量

public class FieldDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //获取所有的成员变量
        Field[] fields = aClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

在这里插入图片描述

然而 为什么我的Person类里面有三个成员变量 可以循环只出了一个

回头 看一下我们的Person类

在这里插入图片描述

除了ID 其他的成员变量都是Private修饰的 那现在我们知道了Field[] getFields()获取所有public修饰的成员变量

所以,来看 Field getField(String name) 就可以分析出 String name 获取指定名字的成员变量 ( getFields() 获取所有public修饰的成员变量) 那么 Field getField(String name) 就是 获取指定名字的public修饰的成员变量。

那么我们获取成员变量可以来干什么?

  1. 赋值

    set(Object obj, Object value) 将指定对象参数上的此 Field对象表示的字段设置为指定的新值。

  2. 获取值

    get(Object obj) 返回该所表示的字段的值 Field ,指定的对象上。

  3. setAccessible(true)

    忽略访问权限修饰符的安全检查 (后面的功能中我们都能用的到)

代码演示:(格式)

public class FieldDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //获取指定名字的public修饰的成员变量
        Field id = aClass.getField("id");
        //设置成员变量id的值
        Person person = new Person();
        id.set(person,8848);
        //获取成员变量id的值
        Object o = id.get(person);
        System.out.println("id是"+o);
    }
}

在这里插入图片描述

上面的两个功能我们学会了那么 下面的两个功能就更加简单:

Field[] getDeclaredFields( ) 获取所有成员变量(不考虑修饰符)

public class FieldgetConstructorDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //不考虑 修饰符
        Field[] declaredFields = aClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
    }
}

在这里插入图片描述

那么Field getDeclaredField(String name) 不就是指定名字的成员变量

那我们来看一下他的 赋值取值

public class FieldgetConstructorDemo01 {
    public static void main(String[] args) throws Exception {
        //通过字符串的方式获取
        Class<?> aClass = Class.forName("Demo02.Person");
        //根据变量名称获取
        Field name = aClass.getDeclaredField("name");
        Person person = new Person();
        //忽略访问权限修饰符的安全检查 (暴力反射 FBI! open the door)
        name.setAccessible(true);
        //赋值
        name.set(person,"Jo级生物");
        //获取
        Object o = name.get(person);
        System.out.println("我是 :"+o);

    }
}

如果 没有setAccessible(true )私有的不能被访问 所以 会报一个 非法的访问异常

在这里插入图片描述

功能演示:(获取构造方法)

public class Demo01 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("ConstructorDemo03.Person");
        //构造方法 类名和方法名是相同的
        //区分 : 参数不一样 而这里要求的参数类型是不同参数的Class对象
        Constructor<?> constructor = aClass.getConstructor(int.class,
                String.class,
                int.class);
        System.out.println(constructor);
    }
}

在这里插入图片描述

Constructor:构造方法
    创建对象:T  newInstance(Object... initargs)

用法:

        Constructor<?> constructor = aClass.getConstructor(int.class,
                String.class,
                int.class);
        //创建对象
        Object o = constructor.newInstance(1, "张三", 20);
        System.out.println(o);

在这里插入图片描述

创建一个空参就能好说了 :

在这里插入图片描述

定义就是一个 可变参的形式

 Constructor<?> constructor = aClass.getConstructor();
        //创建对象
        Object o = constructor.newInstance();
        System.out.println(o);

也可以使用Class对象中的newInstance的方法

Class<?> aClass = Class.forName("ConstructorDemo03.Person");
Object o1 = aClass.newInstance();
System.out.println(o1);

如果说 我们的构造方法是私有的

那么就可以使用 Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)

其实用法与上面的(获取成员变量)基本相同:

public class Demo02 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("ConstructorDemo03.Person");
        //暴力反射
        Constructor<?> dct = aClass.getDeclaredConstructor(int.class,
                String.class,
               int.class);
        dct.setAccessible(true);
        Object o = dct.newInstance(1, "张三", 20);
        System.out.println(o);
    }
}

功能演示: (获取成员方法)

在Person 加入了三个方法:

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

    public Person() {
    }

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

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    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;
    }

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

    public void eat(){
        System.out.println("我在喝刘一碗羊汤");
    }
    public void eat(int count){
        System.out.println("我在刘一碗喝了"+count+"碗羊汤");
    }
    private void swim(){
        System.out.println("我在游泳");
    }
}
public class Demo01 {
    /*
    *  执行方法
    * */
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("MethodDemo04.Person");
        //获得指定名称的方法
        Method method = aClass.getMethod("eat");
        Person person = new Person();
        //执行方法
        method.invoke(person);
        //如果方法中传入了参数
        Method method1 = aClass.getMethod("eat",int.class);
        Person person1 = new Person();
        method1.invoke(person1,60);

        //获取所有的public修饰的方法
         Method[] methods = aClass.getMethods();
         for (Method method2 : methods) {
             System.out.println(method2);
         }
        
        //拿到私有的方法
        Method swim = aClass.getDeclaredMethod("swim");
        Person person2 = new Person();
        swim.setAccessible(true);
        swim.invoke(person2);
    }
}

因为要获取所有的public修饰的方法 方法有很多所以就没有让他执行

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值