Java中的反射机制示例详解

 更新时间:2022年03月09日 15:25:05   作者:不想起床的小张  
反射就是把Java类中的各个成分映射成一个个的Java对象。本文将通过示例详细讲解Java中的反射机制,感兴趣的小伙伴可以跟随小编学习一下

反射

反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制

每一个Java程序执行必须通过编译、加载、链接和初始化四个阶段

1.编译:将.java.文件编译成字节码.class文件

2.加载:查找并加载类的二进制数据

3.链接:

  • 验证:确保被加载类的正确性
  • 为类的静态变量分配内存,并将其初始化为默认值
  • 将类中的符号转换为直接引用

4.初始化:为类的静态变量赋予正确的初始值

什么是Class类

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息

也就是说,无论你是什么对象,总会有有一个隐藏的Class对象与你相对应,而Class的实例表示正在运行的 Java 应用程序中的类和接口。借此,实现了我们Java的反射机制。

获取Class实例的三种方式

实例化对象调用getClass()方法

使用Class类的静态方法forName(),用类的名字获取一个Class实例

运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例

用代码来看一看:

public class reflect {

    public static void main(String[] args) throws ClassNotFoundException {

        Apple apple = new Apple();

        // 使用对象的getClass()方法
        Class a1 = apple.getClass();

        // 使用Class类的静态方法forName()
        Class a2 = Class.forName("p1.apple");

        // 运用.class的方式来获取Class实例
        Class a3 = Apple.class;

        System.out.printf("a1: %s\na2: %s\na3: %s", a1, a2, a3);

    }

}

class Apple {

    private Integer weight;

    private String color;
    
}

打印结果:

a1: class p1.apple
a2: class p1.apple
a3: class p1.apple
进程已结束,退出代码0

通过反射创建类对象

通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。

public class reflect {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        // 通过 Class 对象的 newInstance() 方法
        Class temp1 = Apple.class;
        Apple apple1 = (Apple) temp1.newInstance();
        
        // 通过 Constructor 对象的 newInstance() 方法
        Class temp2 = Apple.class;
        Constructor constructor1 = temp2.getConstructor();
        Apple apple2 = (Apple)constructor1.newInstance();

        // 通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。
        Class temp3 = Apple.class;
        Constructor constructor2 = temp3.getConstructor(Integer.class,String.class);
        Apple apple = (Apple)constructor2.newInstance(2, "Red");
        System.out.println(apple);

    }

}

class Apple {

    private Integer weight;

    private String color;

    // 无参构造器
    public Apple() {
        System.out.println("我是无参构造!");
    }

    // 有参构造器
    public Apple(Integer weight,String color) {
        this.weight = weight;
        this.color = color;
    }

    // 重写方法 方便打印显示对象内容
    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

我是无参构造!
我是无参构造!
Apple{weight=2, color='Red'}

进程已结束,退出代码0

通过反射获取类属性、方法、构造器

public class reflect {

    public static void main(String[] args) throws NoSuchFieldException {

        // 返回一个类中所有可访问的公共字段,包括该类的公共字段和其继承的类的公共字段
        Field[] fields1 = Apple.class.getFields();
        System.out.println("getFields结果");
        Arrays.stream(fields1).forEach(System.out::println);

        // 返回一个类中全部字段,但只包括该类的字段
        Field[] fields2 = Apple.class.getDeclaredFields();
        System.out.println("getDeclaredFields结果");
        Arrays.stream(fields2).forEach(System.out::println);

        // 根据字段名返回一个公开字段
        Field field1 = Apple.class.getField("noThing");
        System.out.println("getField结果");
        System.out.println(field1);

        // 根据字段名返回一个字段
        Field field2 = Apple.class.getDeclaredField("color");
        System.out.println("getDeclaredField结果");
        System.out.println(field2);

        // 同Field Method也有四种获取方式
        // 这里举其中一个例子
        Method[] methods = Apple.class.getDeclaredMethods();
        System.out.println("getDeclaredMethods结果");
        Arrays.stream(methods).forEach(System.out::println);

        // 同上 举一个获取构造器的例子
        Constructor[] constructors = Apple.class.getDeclaredConstructors();
        System.out.println("getDeclaredConstructors结果");
        Arrays.stream(constructors).forEach(System.out::println);

    }

}

class Apple {

    private Integer weight;

    private String color;

    public String noThing;

    public Apple() {

    }

    public Apple(Integer weight, String color) {
        this.weight = weight;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

getFields结果
public java.lang.String p1.Apple.noThing
getDeclaredFields结果
private java.lang.Integer p1.Apple.weight
private java.lang.String p1.Apple.color
public java.lang.String p1.Apple.noThing
getField结果
public java.lang.String p1.Apple.noThing
getDeclaredField结果
private java.lang.String p1.Apple.color
getDeclaredMethods结果
public java.lang.String p1.Apple.toString()
getDeclaredConstructors结果
public p1.Apple()
public p1.Apple(java.lang.Integer,java.lang.String)

更改访问权限和实例赋值

首先,通过field.setAccessible()可更改属性的访问权限

public class reflect {

    public static void main(String[] args) throws NoSuchFieldException {

        // 实例化一个Apple
        Apple apple = new Apple();

        // 获取所有字段 并统一设定为公有属性
        Field[] fields = Apple.class.getDeclaredFields();
        Arrays.stream(fields).forEach( field -> {
            field.setAccessible(true);
            // 打印结果
            System.out.println(field);
            try {
                if (field.getType() == Integer.class) {
                    field.set(apple, 5);
                } else if (field.getType() == String.class) {
                    field.set(apple, "Red");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        // 查看apple结果
        System.out.println(apple);
      
    }

}

class Apple {

    private Integer weight;

    private String color;

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

private java.lang.Integer p1.Apple.weight
private java.lang.String p1.Apple.color
Apple{weight=5, color='Red'}

进程已结束,退出代码0

通过源码文档和打印结果,可见setAccessable()方法并没有改变类字段的访问权限,而是作为一个标志,使得我们反射获取实例过程中可以对其进行操作

运用场景

在我看来,反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。

众所周知,语言有静态语言和动态语言两大分类,静态语言例如C/C++、Java、C#等,动态语言有Python、PHP、JavaScript等。为了让Java语言也有动态语言的特性,有了反射机制,解耦以及提高代码的灵活性。

反射在开发过中或许并不常见,可我们使用的框架工具底层都有反射的存在。动态代理设计模式、JDBC 的数据库的连接、Spring 框架的使用等都应用到了反射机制。

以上就是Java中的反射机制示例详解的详细内容,更多关于Java反射机制的资料请关注脚本之家其它相关文章!

相关文章

  • Java定时任务的三种实现方式

    Java定时任务的三种实现方式

    这篇文章主要给大家介绍了关于Java定时任务的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • Spring Boot 实现Restful webservice服务端示例代码

    Spring Boot 实现Restful webservice服务端示例代码

    这篇文章主要介绍了Spring Boot 实现Restful webservice服务端示例代码,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-11-11
  • 新手小白看过来学JAVA必过IO流File字节流字符流

    新手小白看过来学JAVA必过IO流File字节流字符流

    这篇文章主要介绍了新手小白学JAVA到IO流File字节流字符流的重点,对流不清楚的新手同学快进来学习吧,大佬也可以进来温故一下
    2021-08-08
  • Java序列化常见实现方法代码实例

    Java序列化常见实现方法代码实例

    这篇文章主要介绍了Java序列化常见实现方法代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Java 多线程传值的四种方法

    Java 多线程传值的四种方法

    这篇文章主要介绍了Java 多线程传值的四种方法,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java如何把数组转换为ArrayList

    Java如何把数组转换为ArrayList

    这篇文章主要介绍了Java如何把数组转换为ArrayList,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Tk.mybatis零sql语句实现动态sql查询的方法(4种)

    Tk.mybatis零sql语句实现动态sql查询的方法(4种)

    有时候,查询数据需要根据条件使用动态查询,这时候需要使用动态sql,本文主要介绍了Tk.mybatis零sql语句实现动态sql查询的方法,感兴趣的可以了解一下
    2021-12-12
  • Java文档注释用法+JavaDoc的使用说明

    Java文档注释用法+JavaDoc的使用说明

    这篇文章主要介绍了Java文档注释用法+JavaDoc的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 浅析JAVA中的内存结构、重载、this与继承

    浅析JAVA中的内存结构、重载、this与继承

    这篇文章主要介绍了 JAVA中的内存结构、重载、this与继承的相关资料,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java 反射机制

    Java 反射机制

    这篇文章简要的说明了Java的反射机制,Java的反射是框架设计的灵魂,本文通过例子能看的更加清晰的理解
    2021-06-06

最新评论