JDK1.5 新特性【反射】

news/2024/7/8 2:45:47 标签: java, 开发语言

前言

        今天复习一下反射,说是复习,基本上已经忘干净了,只知道用Spring、Mybatis、JavaFX 的时候加个注解,具体原理就不知道了。所以必须再深入学习一下。

1、设计一个框架?

设计一个框架需要什么技术?

反射机制、自定义注解、设计模式、AOP技术、Netty、Spring 架构、SpringBoot 自定义插件、多线程或 JUC。

2、反射技术

2.1、概念

  • Java中的反射是指程序在运行时动态地获取类的信息(比如方法信息、注解信息、方法参数、类的属性等)以及操作类的成员变量、方法和构造方法的能力。
  • 通过反射,可以在运行时检查类的属性和方法,获取类的构造函数并实例化对象,调用类的成员变量和方法,甚至可以在运行时动态地生成新的类,这使得Java程序具有更大的灵活性和动态性。
  • 但是,反射机制也会导致一些性能上的问题,因为反射调用的速度通常比直接调用要慢得多。

反射机制的核心是在运行时动态地获取类的信息,并通过这些信息来调用类的成员变量和方法,这种能力使得Java程序可以在运行时动态地加载和执行代码,从而实现更加灵活和动态的功能。 

2.2、Java中反射的主要API

  • Class类:用于表示Java类的信息,包括类的名称、父类、接口、构造函数、成员变量和方法等。
  • Constructor类:用于表示Java类的构造函数信息。
  • Method类:用于表示Java类的方法信息。
  • Field类:代表类的成员变量

2.3、应用场景

  • JDBC 加载驱动 Class.forName("com.mysql.cj.jdbc.Driver")
  • Spring 容器框架 IOC 实例化对象
  • 自定义注解生效(反射+AOP)
  • 第三方核心的框架
  • 在 Spring 中每个 Bean 的对象都是通过反射技术来初始化的。
  • 以及在之前 Hadoop 的学习中,当我们自定义的对象需要序列化的时候,我们说必须要有无参构造方法,因为反序列化需要反射调用无参构造函数。

3、使用反射初始化对象

我们以往的学习经历告诉我们,初始化对象的方式无非就是直接 new:

java">User user = new User();

下面给出两种通过反射初始化对象的方式: 

3.1、通过反射实现无参构造

原理:Class 对象的 newInstance 方法会默认执行我们的无参构造方法来初始化对象(所以在定义一个 JavaBean的时候一定要记得写无参构造的方法)。

java">    // 通过反射调用无参构造来初始化对象
    Class<?> aClass = Class.forName("kt.pojo.User");
        // newInstance() 默认执行到我们的无参构造方法来初始化对象
        User user = (User) aClass.newInstance();
        System.out.println(user);

3.2、通过反射实现有参构造

3.2.1、一个标准的 JavaBean

java">package kt.pojo;

import java.util.Objects;

public class User {
    public String name;
    public Integer age;

    public User(){}

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return age.equals(user.age) && Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

注意:这里的 age 属性类型也可以用 int ,区别就是 int 的默认值为 0,Integer 的默认值为 null。

输出结果:

java">User{name='null', age=null}

3.2.2、有参构造实现 

通过我们 Class 对象来获取我们的构造器对象 Constructor,然后调用 Constructor 对象的 newInstacne 方法来实现有参构造。

注意:如果 age 属性类型是 int,那么 getConstructor 的第二个参数应该是 int.class 。 

java">    // 通过反射调用有参构造来初始化对象
    Class<?> aClass = Class.forName("kt.pojo.User");
    // 通过反射调用有参构造来初始化对象
        Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
        User tom = (User) constructor.newInstance("tom", 10);
        System.out.println(tom);

输出结果:

java">User{name='tom', age=10}

4、使用反射给对象的属性赋值

4.1、通过对象给属性赋值

我们通过反射获取到对象,然后调用对象的方法来赋值(必须保证对象的 setter 方法是 public 的):

java">    User user = (User) aClass.newInstance();
        user.setName("tom");
        user.setAge(10);
        System.out.println(user);

运行结果:

java">User{name='tom', age=10}

4.2、通过反射给属性赋值

通过反射获取到 Class 对象,再调用 Class 对象的 getDeclareField 方法获得指定属性的属性对象,最后通过属性的 set 方法来实现赋值:

java">User user = (User) aClass.newInstance();
        //        aClass.getField(); //这个方法会把我们 User 类的父类(这里是Object)中的属性页获取到
        Field name = aClass.getDeclaredField("name");
        name.setAccessible(true);   // 如果属性是私有的(private) 就需要添加访问权限
        Field age = aClass.getDeclaredField("age");
        age.setAccessible(true);    // 如果属性是私有的(private) 就需要添加访问权限
        name.set(user,"tom");
        age.set(user,10);
        System.out.println(user);        

注意:

  • JavaBean 中的属性如果是私有的需要调用属性对象(Field)的 setAccessible 方法传进一个 true 来使得属性可访问。
  • 如果需要使用该对象父类的属性的话,可以使用 getField 方法。

5、通过反射调用方法

我们在上面的 User 类中添加一个 sayHello 方法:

java">public void sayHello(String name){
        System.out.println("hello "+name);
    }

通过 Class 对象的 getDeclaredMethod 方法获取到指定的方法对象 Method,最后调用 Method 对象的 invoke 方法(需要传入执行该方法的对象和需要的参数):

java">    Class<?> aClass = Class.forName("kt.pojo.User");
    User user = (User)aClass.newInstance();
    Method toString = aClass.getDeclaredMethod("sayHello", String.class);
    toString.invoke(user,"Tom");

运行结果:

java">hello Tom


http://www.niftyadmin.cn/n/5194894.html

相关文章

ESP32 Arduino实战协议篇-低功耗蓝牙 (BLE)

ESP32 不仅配备 Wi-Fi,还配备蓝牙和低功耗蓝牙 (BLE)。这篇文章简要介绍了 ESP32 的 BLE。首先,我们将探讨什么是 BLE 以及它的用途,然后我们将使用 Arduino IDE 查看 ESP32 的一些示例。为了简单介绍,我们将创建一个 ESP32 BLE 服务器,以及一个用于查找该服务器的 ESP32 …

SpringBoot中日志的使用log4j

SpringBoot中日志的使用log4j 项目中日志系统是必不可少的&#xff0c;目前比较流行的日志框架有 log4j、logback 等&#xff0c;这两个框架的作者是同一个 人&#xff0c;Logback 旨在作为流行的 log4j 项目的后续版本&#xff0c;从而恢复 log4j 离开的位置。 另外 slf4j(…

INFINI Labs 产品更新 | 发布 Easysearch Java 客户端,Console 支持 SQL 查询等功能

近年来&#xff0c;日志管理平台越来越流行。使用日志管理平台可以实时地、统一地、方便地管理和查看日志&#xff0c;挖掘日志数据价值&#xff0c;驱动运维、运营&#xff0c;提升服务管理效率。 方案架构 Beats 是轻量级采集器&#xff0c;包括 Filebeat、Metricbeat 等。E…

IC设计企业,如何安全、可控、高效的传输设计文档和研发数据?

近年来&#xff0c;半导体的应用领域不断拓展&#xff0c;在全球经济和社会发展中的重要性与日俱增&#xff0c;半导体芯片是数字经济的核心&#xff0c;承载着现代产业发展&#xff0c;具有举足轻重的价值。从半导体行业的角度&#xff0c;IC设计是关键的一环&#xff0c;我国…

Halcon (5):Halcon Solution Guide I basics 导论解析

文章目录 文章专栏前言文章目录翻译文档的说明 结论LOL比赛结局 文章专栏 Halcon开发 前言 今天开始看Halcon的官方文档。由于市面上的教学主要是以基础的语法&#xff0c;算子简单介绍为主。所以我还是得看官方的文本。别的不多说了。有道词英语词典&#xff0c;启动。 还有…

JAVA小游戏 “拼图”

第一步是创建项目 项目名自拟 第二部创建个包名 来规范class 然后是创建类 创建一个代码类 和一个运行类 代码如下&#xff1a; package heima;import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import jav…

针对CSP-J/S的每日一练:Day9

一、审题 题目描述 众所周知&#xff0c;光年是一种距离单位&#xff0c;1光年9460730472580800米。今年5月6日&#xff0c;天文学家在最新一期《天文学与天体物理学》杂志上称&#xff0c;他们发现了一个距离地球只有1000光年的黑洞&#xff0c;这是迄今为止在肉眼可见的恒星…

算法 归并排序MergeSort的理解与C语言实现

归并排序&#xff0c;运用了二分和递归求解的思想&#xff0c;将需要排序的序列每一次递归中从中间切开&#xff0c;分左半和右半&#xff0c;然后将左半右半合并&#xff0c;那么这里就产生了两个函数&#xff0c;一个是MergeSort的切分函数&#xff0c;一个是合并的Merge函数…