Java中的反射

一、简介

1.1 反射概述

在程序运行状态中:

  • 对于任何一个类,都能够获取这个类的所有属性和方法。
  • 对于任意一个对象,都能够调用这个对象的任意一个属性和方法。

这种在运行时动态的获取信息以及动态调用对象的方法的功能称之为反射 reflection

1.2 类加载器

类加载:把class文件加载到内存(JVM内存)的过程称之为类加载。

类加载器:class文件的加载是与ClassLoader完成的,ClassLoader称之为类加载器。

Java默认有三种类加载器:

​ **BootstrapClassLoader:**引导启动类加载器,是用c++语言编写,由JVM在启动时加载初始化的,主要负载加载JAVA_HOME/jre/lib下的类库。

​ **ExtensionClassLoader:**扩展类加载器,它是用java语言编写,且它的父类加载器是Bootstrap。 是由sun.misc.Launcher$ExtClassLoader实现的,主要加JAVA_HOME/jre/lib/ext目录中的类库。它的父加载器是BootstrapClassLoader。

​ **AppClassLoader:**应用程序类加载器,负责加载应用程序classpath目录下的所有jar和class文 件。它的父加载器为ExtensionClassLoader

可以使用 类名.class.getClassLoader() 获取当前类的类加载器。

class文件读取到内存中会被封装成 java.lang.Class 类的对象。
在这里插入图片描述

1.3 双亲委派模型:

​ 如果一个类加载器收到了一个类加载请求。它不会自己去尝试加载这个类,而是把这个请求转交给父类加载器完成。每一层次的类加载器都是如此。因此所有的类加载请求都应该传递到最顶层的的类加载器中,也就是启动类加载器中BootstrapClassLoader。只有到父类加载器反馈自己无法完成这个加载请求(在它的搜索范围内找不到这个类)时,子类加载类才会尝试自己去加载。委派的好处就是避免有些类重复加载。

1.4 反射相关的API

反射相关的api都是在java.lang包中

类、接口名描述
Class表示运行中的类和接口
Constructor表示类中的构造函数
Method表示类中的方法
Filed表示类中的属性
Package表示类所属的包
Modifier表示修饰符
Parameter表示方法的参数

二、获取Class对象

2.1 简介

​ 运行中的class文件是通过Class对象来表示

Class对象是在类加载时由JVM自动创建的,一个类在JVM中只会有一个Class对象。

Class类没有公共的构造方法,不能自己创建Class对象,但是可以获取其实例进行操作。

Class是反射的核心类,要想操作类中的属性和方法,都必须从获取Class对象开始。

2.2 获取Class对象的方式
2.2.1 调用类的class属性
public class Person {
    private String name;
    private String gender;
    public int age;
    
    public Person() {
    }
    public Person(String name) {
        this.name = name;
    }
    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public Person(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public void setNameAge(String name,int age){
        this.name= name;
        this.age= age;
    }
    public int getAge() {
        return age;
    }
    private void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}
 public static void main(String[] args) {
        //已知道有Person这个类,调用该类的class属性
        Class<Person> personClass = Person.class;
        System.out.println("类全名:" + personClass.getName());//类全名:包名+类名
        System.out.println("类名:" + personClass.getSimpleName());
        System.out.println("类所在的包:" + personClass.getPackage());
    }

在这里插入图片描述

2.2.2 调用对象的getClass()方法
public static void main(String[] args) {
        //创建一个person对象
        Person person = new Person();
        //获取Class对象,调用getClass()方法
        Class<? extends Person> personClass = person.getClass();
        System.out.println("类全名:" + personClass.getName());//类全名:包名+类名
        System.out.println("类名:" + personClass.getSimpleName());
        System.out.println("类所在的包:" + personClass.getPackage());
    }

在这里插入图片描述

2.2.3 调用Class类的forName()静态方法(推荐使用)
public static void main(String[] args) throws ClassNotFoundException {
        //forName方法中需要填写类的全名(包名+类名)
        Class personClass = Class.forName("com.ly.zreflection.Person");
        System.out.println("类名:" +personClass.getSimpleName());
        System.out.println("类加载器:" + personClass.getClassLoader());
    }

在这里插入图片描述

2.3 特殊类的类对象

基本数据类型的类对象:

​ 基本数据类型.class

​ 包装类.type

基本数据类型包装类对象:

​ 包装类.class

三、操作Constructor

3.1 获取公有的无参构造方法,再通过无参构造创建对象
public static void main(String[] args) throws Exception {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //获取一个无参构造方法
        Constructor constructor = clzss.getConstructor();//获取公有
        //获取对象
        Object o = constructor.newInstance();
        System.out.println("无参构造获取对象:" + o);
    }

在这里插入图片描述

3.2 获取公有的全参构造方法,创建对象
public static void main(String[] args) throws Exception {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //获取全参的构造方法(公有)
        Constructor allParameter = clzss.getConstructor(String.class, String.class, int.class);
        //创建对象并给对象赋值
        Object o1 = all.newInstance("lisi", "男", 18);
        System.out.println("全参构造创建对象:" + o1);
    }

在这里插入图片描述

3.3 获取私有的有参构造,创建对象
public static void main(String[] args) throws Exception {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //获取指定参数的私有的构造方法
        Constructor pri = clzss.getDeclaredConstructor(String.class, int.class);
        //true则表示忽略访问权限检查 (可以访问任何权限的方法)
        pri.setAccessible(true);
        Object o = pri.newInstance("zhangsan", 20);
        System.out.println("私有的有参构造创建对象:" + o);
    }

在这里插入图片描述

3.4 获取所有的构造方法
 public static void main(String[] args) throws Exception {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //获取所有的构造方法(包含公有和私有的)
        Constructor[] declaredConstructors = clzss.getDeclaredConstructors();
        for (Constructor constructor :declaredConstructors){
            System.out.println(constructor);
        }
    }

在这里插入图片描述

四、操作Method

4.1 获取全部的方法
 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //通过类对象获取所有方法(包含公有、私有)
        Method[] methods = clzss.getDeclaredMethods();
        for (Method method:methods){
            System.out.println(method);
        }

    }

在这里插入图片描述

4.2 获取指定参数类型及个数的方法,并通过方法给对象赋值
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
        //获取类对象
        Class clzss = Class.forName("com.ly.zreflection.Person");
        //获取一个无参构造
        Constructor declaredConstructor = clzss.getConstructor();
        //通过无参构造创建一个对象
        Object o1 = declaredConstructor.newInstance();
        //获取类中指定方法                      方法名        参数类型         参数类型
        Method setNameAndAge = clzss.getMethod("setNameAge", String.class, int.class);
        //参数1. 哪个对象要执行的setNameAndAge方法
        //参数2. 调用方法传递的参数 0-n
        setNameAndAge.invoke(o1,"wangwu",20);
        System.out.println(o1);
    }

在这里插入图片描述

4.3 获取私有方法,并给对象赋值
public static void main(String[] args) throws Exception{
        //获取类对象
        Class clazz  = Class.forName("com.ly.zreflection.Person");
        //获取一个无参构造
        Constructor constructor = clazz.getConstructor();
        //通过无参构造创建一个对象
        Object o = constructor.newInstance();
        //通过类对象获取一个私有的方法
        Method setAge = clazz.getDeclaredMethod("setAge", int.class);
        setAge.setAccessible(true);//打开权限,为了后面可以通过方法设置值
        //调用invoke方法,给对象赋值
        setAge.invoke(o,18);
        System.out.println("通过setAge方法给对象赋值:" + o);
    }

在这里插入图片描述

五、操作Filed

5.1 获取一个公有的类属性,并给对象赋值
public static void main(String[] args) throws Exception{
        //获取类对象
        Class  clazz = Class.forName("com.ly.zreflection.Person");
        //获取一个公共的类属性
        Field age = clazz.getField("age");//传入一个属性名称
        System.out.println("这个属性的名称是:" + age.getName());
        //通过类对象获取一个无参构造
        Constructor constructor = clazz.getConstructor();
        //通过无参构造创建一个对象
        Object o = constructor.newInstance();
        //给对象赋值
        age.set(o,20);//第一个参数是要给赋值的对象,第二个为要赋的值
        System.out.println("通过属性为对象赋值:" + o);

    }

在这里插入图片描述

5.2 获取一个私有的类属性,并给对象赋值
public static void main(String[] args) throws Exception{
        //获取类对象
        Class  clazz = Class.forName("com.ly.zreflection.Person");
        //通过类对象获取一个无参构造
        Constructor constructor = clazz.getConstructor();
        //通过无参构造创建一个对象
        Object o = constructor.newInstance();
        //获取一个私有的类属性
        Field name = clazz.getDeclaredField("name");//传入一个属性名称
        //打开权限
        name.setAccessible(true);
        //给对象赋值
        name.set(o,"jack");//第一个参数是要给赋值的对象,第二个为要赋的值
        System.out.println("这个属性的名称是:" + name.getName());
        System.out.println("通过属性为对象赋值:" + o);
    }

在这里插入图片描述

5.3 获取类中所有的属性
 public static void main(String[] args) throws Exception{

        //获取类对象
        Class  clazz = Class.forName("com.ly.zreflection.Person");
        //获取一个所有的类属性(私有、公有)
        Field[] fields = clazz.getDeclaredFields();
        for (Field filed:fields) {
            System.out.println("属性名称为:" + filed.getName());
            System.out.println("属性的类型为:" + filed.getGenericType());
            System.out.println();
        }
    }

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值