Java反射

作者: h2coder | 来源:发表于2022-11-19 00:29 被阅读0次

概述

在程序的运行过程中, 通过Class对象得到类中的信息(构造方法,成员方法,成员变量), 并操作他们。这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。

  • 反射的应用场景

    • IDEA的智能提示
    • 框架 Spring、SpringMVC、Mybatis 等的底层原理
  • 利用反射调用它类中的属性和方法时,无视修饰符。

  • 使用反射创建对象,代码更复杂,功能更强大灵活。

Class对象

在Java中有一个类,类名就叫Class。Class类创建的对象我们成为Class对象

public class Class<T> {
    保存类中的信息(构造方法, 成员方法, 成员变量)
}
  • 类结构

Class对象会保存类中的信息(构造方法, 成员方法, 成员变量等)
有了Class对象就能得到类中的所有信息。可以说得到Class对象反射就完成了一半。

class Class {
    //成员变量
    Field[] fs;
    //构造器
    Constructor[] cs;
    //成员方法
    Method[] ms;
}

获取Class对象的方式

三种获取Class对象的方式

  • 对类名.class
Class<Person> clazz1 = Person.class;
  • 对象.getClass()
Person p = new Person();
Class<? extends Person> clazz2 = p.getClass();
  • Class.forName("类全名");
Class<?> clazz3 = Class.forName("com.zh.reflection.model.Person");

测试的实体类

class A {
    public int a;
}

public class Person extends A {
    public int aa;

    //成员变量
    private String name;
    private int age;

    //-------构造方法-------
    public Person() {
    }

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

    private Person(String name) {
        this.name = name;
    }

    protected Person(int age) {
        this.age = age;
    }
    //-----------------------


    //-------get和set方法-------
    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 add(int a, int b) {
        int c = a + b;
        System.out.println("相加结果:" + c);
    }

    private int work(int hour) {
        System.out.println("一天工作" + hour + "小时");
        return hour * 100; //工资
    }

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

准备工作

  • 使用反射,先要获取Class对象
//获取Person类的字节码对象
Class<Person> clazz = Person.class;

反射构造方法(Constructor)

Class类中获取构造方法

  • Constructor<?>[] getConstructors():返回public修饰的所有构造方法对象的数组
//获取所有公开public修饰的构造方法
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
    System.out.println(constructor);
}
  • Constructor<T> getConstructor(Class<?>... parameterTypes):返回public修饰的单个构造方法对象
//无参构造,getConstructor():公开修饰的
Constructor<Person> c2 = clazz.getConstructor();
System.out.println(c2);
  • Constructor<?>[] getDeclaredConstructors():返回任意权限的所有构造方法对象的数组
//获取所有任意权限的构造方法
Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
for (Constructor<?> declaredConstructor : declaredConstructors) {
    System.out.println(declaredConstructor);
}
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回任意权限的单个构造方法对象
//无参构造,getDeclaredConstructor():任意权限修饰的
Constructor<Person> c2 = clazz.getDeclaredConstructor();
System.out.println(c2);
  • 获取带参构造方法
//获取带参构造方法
Constructor<Person> c3 = clazz.getDeclaredConstructor(String.class, int.class);
System.out.println(c3);

反射构造方法创建对象

Constructor类中用于创建对象的方法

  • Constructor类中的方法
    • T newInstance(Object... initargs):根据指定的构造方法创建对象
    • setAccessible(boolean flag):设置为true,表示允许对私有权限的访问
//反射获取无参构造方法
Constructor<Person> c1 = clazz.getConstructor();
//使用构造器创建对象
Person p1 = c1.newInstance();
System.out.println(p1);

//反射获取有参的构造方法,newInstance() 要传入实参
Constructor<Person> c2 = clazz.getConstructor(String.class, int.class);
Person p2 = c2.newInstance("张三", 18);
System.out.println(p2);

//反射获取私有的带参构造方法
Constructor<Person> c3 = clazz.getDeclaredConstructor(String.class);
//设置权限为允许范围,只针对对非空开
c3.setAccessible(true);
Person p3 = c3.newInstance("李四");
System.out.println(p3);

反射方法(Method)

Class类中获取成员方法

  • Method[] getMethods():返回所有public的成员方法对象的数组,包括继承的。
//获取所有公开public的方法(包括从父类继承而来的public方法)
Method[] ms1 = clazz.getMethods();
for (Method method : ms1) {
    System.out.println(method);
}
  • Method getMethod(String name, Class<?>... parameterTypes) :返回单个public的成员方法对象(参数name:表示方法名 ;参数parameterTypes:表示方法的形参类型)
//获取公开的成员方法
Method ms3 = clazz.getMethod("add", int.class, int.class);
System.out.println(ms3);
  • Method[] getDeclaredMethods():返回所有成员方法对象的数组,不包括继承的
//获取所有任意权限的方法(不包括父类,只包含本类的)
Method[] ms2 = clazz.getDeclaredMethods();
for (Method method : ms2) {
    System.out.println(method);
}
  • Method getDeclaredMethod(String name, Class<?>... parameterTypes):返回单个成员方法对象(参数name:表示方法名 ;参数parameterTypes:表示方法的形参类型)
//获取单个任意权限的成员方法
Method ms4 = clazz.getDeclaredMethod("add", int.class, int.class);
System.out.println(ms4);

反射成员方法并调用

  • Method类中的方法

    • Object invoke(Object obj, Object... args)
      • 参数obj:调用成员方法的对象。(如果调用的是静态方法,该参数为null即可)
      • 参数args :可变参数,表示调用方法时传递的实参(如果没有就不写)
      • 返回值Object :方法的返回值(如果没有就不用接)
  • 先创建类实例,提供给后续反射调用方法

//反射创建对象实例
Constructor<Person> c1 = clazz.getConstructor();
Person person = c1.newInstance();
  • 反射获取公开public成员方法
//反射获取公开public成员方法
Method ms1 = clazz.getMethod("add", int.class, int.class);
//调用成员方法,需传入实例对象和实参
ms1.invoke(person, 1, 2);
  • 反射获取私有成员方法
//反射获取私有成员方法
Method ms2 = clazz.getDeclaredMethod("work", int.class);
//设置为公开访问
ms2.setAccessible(true);
Object result = ms2.invoke(person, 8);
System.out.println(result);

反射成员变量(Field)

Class类中获取成员变量

  • Field getField(String name):返回单个公共成员变量对象
Field f1 = clazz.getField("aa");
System.out.println(f1);
  • Field[] getFields():返回所有公共成员变量对象的数组,包括继承的public成员变量
//获取公开的成员变量(包括从父类中继承的公开的变量)
Field[] fs1 = clazz.getFields();
for (Field field : fs1) {
    System.out.println(field);
}
  • Field getDeclaredField(String name):返回单个成员变量对象
Field f2 = clazz.getDeclaredField("name");
System.out.println(f2);
  • Field[] getDeclaredFields():返回所有本类成员变量对象的数组。不包括继承的
//获取任意权限的成员变量(只能是本类的,不包括父类的)
Field[] fs2 = clazz.getDeclaredFields();
for (Field declaredField : fs2) {
    System.out.println(declaredField);
}

反射成员变量修改值、获取值

  • Field类中的方法
    • void set(Object obj, Object value):赋值。参数obj为成员变量所在的对象,参数value为成员变量的值
    • Object get(Object obj) :获取值。参数obj为成员变量所在的对象
//获取单个成员变量
Field f1 = clazz.getDeclaredField("age");
System.out.println(f1);
//设置为可访问
f1.setAccessible(true);
//变量赋值,set(调用者、实参值)
f1.set(person, 18);
//变量取值,get(调用者)
Object age = f1.get(person);
System.out.println(age);

相关文章

  • 博客地址

    java注解-01、java注解-02、Git面试资源java反射-01、java反射-02、java反射-03为...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • 反射之一

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • 反射之二

    总结内容源自一下文章粗浅看java反射机制反射机制应用实践谈谈java反射机制Java Reflection(反射...

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • Java 反射机制

    Java 反射机制 什么是反射 Java 反射是Java语言的一个很重要的特征,它使得Java具体了“动态性”。 ...

  • 一探究竟:Java反射效率低的原因到底在哪?

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • 面试官说:大家都说 Java 反射效率低,你知道原因在哪里么

    预备知识 了解 Java 反射基本用法 看完本文可以达到什么程度 了解 Java 反射原理及 Java 反射效率低...

  • Java面试题之JavaSE高级

    一、Java中的反射 1.说说你对Java中反射的理解 java中的反射首先是能够获取到Java...

网友评论

    本文标题:Java反射

    本文链接:https://www.haomeiwen.com/subject/psjmxdtx.html