首页 > 编程语言 >Java零基础-反射

Java零基础-反射

时间:2023-12-20 12:07:00浏览次数:27  
标签:反射 Java String 基础 clazz 方法 Class

前言

Java是目前最流行的开发语言之一,在软件开发领域广泛应用。反射是Java的一项重要特性,它使得程序在运行时可以动态地获取和操作类、方法、属性等信息,极大地提高了Java的灵活性和可扩展性。

本文将介绍Java反射的基本概念、使用方法、应用场景和优缺点,旨在为Java初学者提供一份简明易懂的指南。

摘要

本文主要分为以下几个部分:首先介绍Java反射的基本概念;然后通过源代码解析,详细讲解如何使用反射获取类信息、创建对象、调用方法、访问属性等;接着根据实际应用场景,分析了反射技术的优缺点;最后给出了类代码方法介绍和测试用例,以便读者更好地理解和实践Java反射。

简介

Java反射机制是指在程序运行时,对于任意一个类都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个方法和属性。它是Java的一项重要特性,提高了程序的灵活性和可扩展性,常用于框架设计、动态代理、编译器等领域。

反射是Java语言反映本身特点的体现之一,Java语言必须在虚拟机中进行运行,所以Java程序会首先被编译成字节码,然后由虚拟机进行解释执行。这种运行方式决定了Java程序可以在运行时获取自身的信息,这种自我描述的能力就是Java反射机制。

源代码解析

Java反射主要包括以下几个步骤:获取Class对象、创建对象、调用方法、访问属性。下面分别进行详细解析。

获取Class对象

在Java中,如果要使用反射机制,首先需要获取到要操作的类的Class对象。Class对象是由JVM在加载类时自动创建的,可以通过以下几种方法获取:

方法一:使用.class语法

这是最常用的获取Class对象的方法,通过类名后面加上".class"即可。例如:

Class<?> clazz = String.class;

方法二:使用Class.forName()方法

这个方法会动态地加载类并返回Class对象。例如:

Class<?> clazz = Class.forName("java.lang.String");

方法三:使用对象的.getClass()方法

可以通过对象的getClass()方法来获取Class对象。例如:

String str = "Hello, world!";
Class<?> clazz = str.getClass();

创建对象

获取到Class对象之后,可以通过它来创建对象。创建对象有两种方法:

方法一:使用Class.newInstance()方法

通过Class对象的newInstance()方法可以直接创建对象,前提是该类必须有一个无参构造方法。例如:

Class<?> clazz = String.class;
String str = (String) clazz.newInstance();

方法二:使用Constructor对象

如果想要创建有参构造方法的对象,可以先获取Constructor对象,然后使用它来创建对象。例如:

Class<?> clazz = String.class;
Constructor<?> constructor = clazz.getConstructor(String.class);
String str = (String) constructor.newInstance("Hello, world!");

调用方法

通过Java反射机制,可以在运行期间执行任意一个类的方法。调用方法的步骤如下:

步骤一:获取Method对象

可以通过Class对象的getDeclaredMethod()或getMethod()方法来获取Method对象。前者可以获取私有方法,后者只能获取公共方法。例如:

Class<?> clazz = String.class;
Method method = clazz.getMethod("length");

步骤二:调用Method对象的invoke()方法

调用Method对象的invoke()方法可以执行方法,前提是该方法的调用者对象已经初始化。例如:

Class<?> clazz = String.class;
Method method = clazz.getMethod("length");
String str = "Hello, world!";
int length = (int) method.invoke(str);

访问属性

通过Java反射机制,可以在运行期间访问任意一个类的属性。访问属性的步骤如下:

步骤一:获取Field对象

可以通过Class对象的getDeclaredField()或getField()方法来获取Field对象。前者可以获取私有属性,后者只能获取公共属性。例如:

Class<?> clazz = String.class;
Field field = clazz.getDeclaredField("value");

步骤二:调用Field对象的get()或set()方法

调用Field对象的get()或set()方法可以获取或设置属性的值,前提是该属性的访问权限允许。例如:

Class<?> clazz = String.class;
Field field = clazz.getDeclaredField("value");
String str = "Hello, world!";
char[] value = (char[]) field.get(str);
value[6] = ',';
System.out.println(str);  // Hello, world!

应用场景案例

Java反射机制常用于以下场景:

  1. 框架设计:例如Spring框架,通过反射技术实现类的自动装配、动态代理等功能。
  2. 动态代理:例如Java自带的代理类,通过反射机制生成代理对象,然后在代理对象中调用真正的方法和属性。
  3. 编译器:例如Java编译器,通过反射技术读取和分析类文件,然后生成字节码。

优缺点分析

Java反射机制有以下优点:

  1. 灵活性高:可以在运行时动态地获取和操作类、方法、属性等信息,提高程序的灵活性和可扩展性。
  2. 可以减少重复代码:例如Spring框架中的类自动装配功能,通过反射技术可以避免大量繁琐的手动装配工作。
  3. 动态性强:可以在程序运行时动态地加载、卸载、更新类文件,实现热部署等功能。

但是Java反射机制也有以下缺点:

  1. 性能较低:反射机制中涉及到的类加载、方法调用、字段访问等操作都比较耗时,容易造成性能瓶颈。
  2. 安全性较低:反射机制可以绕过Java的访问控制机制,直接访问私有方法和属性,容易造成安全隐患。

因此,在使用Java反射机制时,需要根据实际情况进行权衡,避免滥用而造成不必要的性能和安全问题。

类代码方法介绍

代码实现了获取Class对象、创建对象、调用方法、访问属性等基本操作。

public class ReflectionDemo {
    public static void main(String[] args) throws Exception {
        // 获取Class对象的三种方法
        Class<?> clazz1 = String.class;
        Class<?> clazz2 = Class.forName("java.lang.String");
        String str = "Hello, world!";
        Class<?> clazz3 = str.getClass();

        // 创建对象的两种方法
        String str1 = (String) clazz1.newInstance();
        Constructor<?> constructor = clazz2.getConstructor(String.class);
        String str2 = (String) constructor.newInstance("Hello, world!");

        // 调用方法
        Method method = clazz1.getMethod("length");
        int length = (int) method.invoke(str);

        // 访问属性
        Field field = clazz1.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(str);
        value[6] = ',';

        System.out.println(length);  // 13
        System.out.println(str);    
	}
}
## 测试用例

下面给出一组测试用例,以便读者更好地理解和实践Java反射。

```java
public class ReflectionTest {
    private String name;
    public int age;

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

    private void privateMethod() {
        System.out.println("This is a private method.");
    }

    public void publicMethod() {
        System.out.println("This is a public method.");
    }

    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<?> clazz = ReflectionTest.class;

        // 创建对象
        Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
        ReflectionTest test = (ReflectionTest) constructor.newInstance("John", 20);

        // 调用私有方法
        Method privateMethod = clazz.getDeclaredMethod("privateMethod");
        privateMethod.setAccessible(true);
        privateMethod.invoke(test);

        // 调用公共方法
        Method publicMethod = clazz.getMethod("publicMethod");
        publicMethod.invoke(test);

        // 访问公共属性
        Field publicField = clazz.getField("age");
        System.out.println("The age is " + publicField.get(test));

        // 访问私有属性
        Field privateField = clazz.getDeclaredField("name");
        privateField.setAccessible(true);
        privateField.set(test, "Tom");
        System.out.println("The name is " + privateField.get(test));
    }
}

测试结果如下:

This is a private method.
This is a public method.
The age is 20
The name is Tom

可以看到,通过Java反射机制,我们成功获取了ReflectionTest类的Class对象,创建了ReflectionTest对象,调用了私有方法、公共方法,访问了公共属性、私有属性,并成功地修改了私有属性的值。

结论

Java反射机制是Java语言的一项重要特性,可以在运行时动态地获取和操作类、方法、属性等信息,提高程序的灵活性和可扩展性。但是反射机制也有性能较低、安全性较低等缺点,需要谨慎使用。在实际应用中,可以根据需求和优缺点进行权衡,在合适的场景下选择使用Java反射技术,以便更好地满足业务需求。

标签:反射,Java,String,基础,clazz,方法,Class
From: https://blog.51cto.com/u_15700799/8905205

相关文章

  • Java基本数据类型、包装类及拆装箱详解
    Java的基本数据类型和对应的包装类是Java语言中处理数据的两个关键概念。基本数据类型提供了简单而高效的方式来存储数据,而包装类使得基本数据类型具有对象的特性。本文将深入探讨基本数据类型与包装类的应用场景及详细描述,并对自动拆箱和装箱的源码实现进行分析。基本数据类型与包......
  • docker 常用基础镜像打包
    JAVADockerfile#8的镜像比较小,但是在某些机器运行可能会有问题#FROMopenjdk:8-jdk-alpine#ARM机器推荐#FROMarm64v8/openjdk:17-jdkFROMopenjdk:17-jdk-alpineENVLANGen_US.UTF-8RUNecho"http://mirrors.huaweicloud.com/alpine/v3.6/main">/etc/apk/reposito......
  • java 特殊操作流
    一、输入流和输出流  1、输入流 2、输出流 二、字节打印流和字符打印流 1、字节打印流 2、字符打印流 三、对象序列化流和对象反序列化流1、对象序列化流 ......
  • 【java】工业园区高精准UWB定位系统源码
    UWB(ULTRAWIDEBAND,UWB)技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。UWB定位系统依托在移动通信,雷达,微波电路,云计算与大数据处理等专业领域的多年积累,自主研发,开发并产业化的一套UWB精确定位系统,最高定位精......
  • Java8 list的lambda表达式
    List<PersonList>list=newArrayList<PersonList>(){{add(newPersonList("张三","1"));add(newPersonList("李四","2"));add(newPersonList("王五","3"));add(newPersonLi......
  • 中电金信:金融电子化 | 打磨算力基础设施,赋能金融业数字化转型
    10月8日,工信部、人民银行等六部门联合印发《算力基础设施高质量发展行动计划》(以下简称《行动计划》),在行业和产业界吸引了信息产业和相关应用行业的广泛关注。作为引领我国算力基础设施建设的重要指南,《行动计划》为我国信息产业带来哪些深远影响?对金融业算力基础设施建设会带来......
  • Kubernetes基础总结
    一、k8s简介kubernetes——容器、分布式架构kubernetes本质是一组服务器集群,可以在集群的每个节点上运行特定的程序,来对节点中的容器进行管理。主要功能:自我修复弹性伸缩——自动调整运行的容器数量服务发现——自动找依赖负载均衡——自动实现请求的负载均衡版本退回存......
  • NX2306 基础-重新学习☆☆☆
    【写在每个笔记前面:个人学习记录,如有错误,烦请指正,不胜感激。】因为自己有很多野路子的操作,效率在很大程度上被限制了,于是觉得更有必要重新全面学习一下基本操作。一是学习更多的规范化操作;二是将零散知识点整理成体系化的内容,如下仅补充自己的漏洞,持续更新。 鼠标:中键:自己在......
  • 精通Quartz:Java中的时间管理与任务调度专家
    Quartz,一个在Java应用中无可替代的时间管理与任务调度库,以其独特的功能和灵活性广受开发者青睐。得名于“石英”,Quartz不仅象征着时间的精确性,也体现了其在任务调度领域的核心地位。本文将深入剖析Quartz的内部工作原理和最佳实践,帮助开发者更好地理解和运用这一强大的库。Quartz......
  • 十七、组件-基础组件-Button
    Button按钮组件,可快速创建不同样式的按钮。方法1:Button(options?:{type?:ButtonType,stateEffect?:boolean})方法2:Button(label?:ResourceStr,options?:{type?:ButtonType,stateEffect?:boolean})使用文本内容创建相应的按钮组件,此时Button无法包含子组件。 案例代码:@Entr......