栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

反射:框架设计的灵魂

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

反射:框架设计的灵魂

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

  反射的好处:

  1. 可以在程序运行过程中,操作这些对象
  2. 可以解耦,提高程序的可扩展性
1. 获取 Class 对象的方式

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

  方式二:类名.class:通过类名的属性 class 获取

  方式三:对象.getClass():getClass() 方法在 Object 类中定义着


  注意:同一个字节码文件在一次程序的运行中,只会被加载一次,无论通过哪一种方式获取的 Class 对象都是同一个。

package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
package com.basic;

import com.entity.Person;

public class Demo {

    public static void main(String[] args) throws ClassNotFoundException {
        // 此方式获取 Class 多用于配置文件中,将类名定义在配置文件中,读取文件,加载类
        Class personClass1 = Class.forName("com.entity.Person"); // 包名+类名:全类名
        System.out.println(personClass1);

        // 多用于参数的传递(我们经常用)
        Class personClass2 = Person.class;
        System.out.println(personClass2);

        Person p = new Person();
        Class personClass3 = p.getClass();
        System.out.println(personClass3);

        // 比较3个 Class 实例是否相等
        System.out.println(personClass1 == personClass2);
        System.out.println(personClass2 == personClass3); // 结果都为 true,所以创建的都是同一个实例,只会加载一次,产生一个实例
    }
}
2. 利用 Class 对象获取成员变量们
  • Field[] getFields():获取所有 public 修饰的成员变量
  • Field getField(String name):获取指定名称的 public 修饰的成员变量
  • Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
  • Field getDeclaredField(String name):获取指定名称的成员变量,不考虑修饰符
  • void set(Object obj, Object value):给成员变量设置值
  • get(Object obj):获取成员变量的值
  • setAccessible(true):暴力反射,使其能够访问 private 修饰的成员变量
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
    public String a;
    public String testA;
    protected String b;
    String c;
}

package com.basic;

import com.entity.Person;

import java.lang.reflect.Field;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        // 获取到 Class 实例
        Class personClass = Person.class;
        // 获取所有 public 修饰的成员变量
        Field[] fields = personClass.getFields();
        System.out.println(Arrays.toString(fields));

        // 获取指定名称 public 修饰的成员变量
        Field testA = personClass.getField("testA");
        System.out.println(testA);
        // 给字段设置值
        Person p = new Person();
        testA.set(p, "张三"); // 通过反射的方式设置值
        // 取字段的值
        System.out.println(testA.get(p)); // 通过反射的方式取值

        // 获取所有的成员变量,不考虑修饰符
        Field[] declaredFields = personClass.getDeclaredFields();
        System.out.println(Arrays.toString(declaredFields));

        // 获取指定名称的成员变量,不考虑修饰符
        Field name = personClass.getDeclaredField("name");
        System.out.println(name);
        // 给 private 字段设置值
        name.setAccessible(true); // 暴力反射,使其能够访问 private 的修饰符的变量
        name.set(p, "李四");
        System.out.println(name.get(p));
    }
}
3. 利用 Class 对象获取构造方法
  • Constructor[] getConstructors():获取所有 public 修饰的构造方法
  • Constructor getConstructor(类…parameterfTypes):获取指定参数列表的 public 修饰的构造方法
  • Constructor getDeclaredConstructor(类…parameterfTypes):获取指定参数列表的构造方法,不考虑修饰符
  • Constructor[] getDeclaredConstructors():获取所有的构造方法,不考虑修饰符
  • T newInstance(Object…initargs):用得到的构造方法创建对象
  • 如果使用空参构造函数创建对象,操作可以简化:Class 对象的 newInstance 方法
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;
}
package com.basic;

import com.entity.Person;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取到 Class 实例
        Class personClass = Person.class;

        // 获取所有 public 修饰的构造方法
        Constructor[] constructors = personClass.getConstructors();
        System.out.println(Arrays.toString(constructors));

        // 获取指定名称的 public 修饰的构造方法
        Constructor constructor = personClass.getConstructor(String.class, Integer.class);
        System.out.println(constructor);
        // 用反射的方式去创建对象
        Person person = constructor.newInstance("张三", 18);
        System.out.println(person);

        // 获取空参的构造方法的简化模式
        Person person1 = personClass.newInstance();
        System.out.println(person1);
    }
}
4. 利用 Class 对象获取成员方法们
  • Method[] getMethods():获取类里面所有的 public 方法,包括父类里面的 pubic 方法
  • Method getMethod(String name,类…parameterTypes):获取指定的 public 修饰的方法
  • Method[] getDeclaredMethods():获取类里面声明的所有方法,不包括父类的方法
  • Method getDeclaredMethod(String name, 类…parameterTypes)
  • Object invoke(Object obj, Object…args):执行方法
  • String getName:获取方法名称
package com.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private Integer age;

    private String lookMovie(String movieName, int age) {
        System.out.println(movieName + "::" + age);
        return movieName;
    }
}
package com.basic;

import com.entity.Person;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class Demo {

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        // 获取到 Class 实例
        Class personClass = Person.class;

        // 获取所有 public 修饰的方法(包括父类的方法)
        Method[] methods = personClass.getMethods();
        System.out.println(Arrays.toString(methods));

        // 获取指定的 public 修饰的方法
        Method setName = personClass.getMethod("setName", String.class);
        System.out.println(setName);
        // 执行这个方法
        Person person = personClass.newInstance(); // 用反射的方式创建空参构造方法
        setName.invoke(person, "张三"); // 执行方法
        System.out.println(person);

        // 获取所有的方法(不包含父类的方法)
        Method[] declaredMethods = personClass.getDeclaredMethods();
        System.out.println(Arrays.toString(declaredMethods));

        // 获取指定的方法(private 和 public 修饰都可以)
        Method lookMovie = personClass.getDeclaredMethod("lookMovie", String.class, int.class);
        System.out.println(lookMovie);
        // 执行私有方法
        lookMovie.setAccessible(true); // 暴力反射,使执行 private 修饰的方法不报错
        Object invoke = lookMovie.invoke(person, "李四", 28);
        System.out.println(invoke);
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/573000.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号