java核心基础--java反射机制详解

简介: 在详细了解反射机制之前,我们先来了解一下java代码在计算机中的运行过程:比如当我们编写好一个类:Student.java,里面包含学生的姓名和年龄,构造方法,其他方法。

微信搜索《Java鱼仔》,每天一个知识点不错过


(一)什么是反射?


反射就是将类的各个组成部分封装为其他对象。


在详细了解反射机制之前,我们先来了解一下java代码在计算机中的运行过程:


比如当我们编写好一个类:Student.java,里面包含学生的姓名和年龄,构造方法,其他方法。


第一个阶段:Source阶段


javac会把我们写的代码编译成.class字节码文件,保存在硬盘中,这个文件中保存着该类的类名,成员名,构造方法等等。


第二个阶段:Class阶段


Class阶段会把字节码文件中的信息转化成class类对象,比如成员变量用Field[]保存,构造方法用Constructor[]保存,成员方法用Method[]保存


第三个阶段:Runtime阶段


通过new Student(),根据第二个阶段的类对象创建出Student对象 这里的第二个阶段,将类的各个组成部分封装为其他对象就是反射机制。


反射的好处:


1.可以在程序运行过程中操作对象。


2.解耦,提高程序可扩展性。


(二)获取字节码Class对象的三种方式


获取Class对象有三种方式,分别对应于前面的三个阶段:


1.对应于第一个阶段的方法是将字节码文件加载进内存中:



class.forname("全类名");

2.第二个阶段已经生成了class类对象,因此方法如下:


类名.class;

3.第三个阶段生成了对象,方法如下:


对象.getclass();

注意:


同一个字节码文件(.class)在一次程序运行过程中只会被加载一次,通过以上三种方法创建的class对象是同一个。


通过代码演示: 新建Student类:


publicclassStudent {
privateStringname;
privateintage;
//方便后期测试的成员变量publicinta;
publicStudent(){}
publicStudent(Stringname, intage,inta) {
this.name=name;
this.age=age;
this.a=a;
    }
publicStringgetName() {
returnname;
    }
publicvoidsetName(Stringname) {
this.name=name;
    }
publicintgetAge() {
returnage;
    }
publicvoidsetAge(intage) {
this.age=age;
    }
@OverridepublicStringtoString() {
return"Student{"+"name='"+name+'\''+", age="+age+", a="+a+'}';
    }
}

测试获取Class对象的三种方式


packagecom.sdxb.reflect;
publicclassreflectTest {
publicstaticvoidmain(String[] args) throwsClassNotFoundException {
//方法一Classcls1=Class.forName("com.sdxb.reflect.Student");
System.out.println(cls1);
//方法二Classcls2=Student.class;
System.out.println(cls2);
//方法三Studentstudent=newStudent();
Classcls3=student.getClass();
System.out.println(cls3);
//判断是否是同一对象System.out.println(cls1==cls2);
System.out.println(cls1==cls3);
    }
}

(三)Class获取对象方法


1.1 获取成员变量


FieldgetField(Stringname) //获取指定名称public修饰的成员变量Field[] getFields()  //获取所有public修饰的成员变量FieldgetDeclaredField(Stringname) //获取指定名称成员变量Field[] getDeclaredFields()  //获取所有成员变量

1.2 操作成员变量


Objectget(Objectobj)  //通过Field获取对象voidset(Objectobj, Objectvalue)  //修改Field的值

通过代码演示


publicclassFieldTest {
publicstaticvoidmain(String[] args) throwsClassNotFoundException, NoSuchFieldException, IllegalAccessException {
Classcls=Class.forName("com.sdxb.reflect.Student");
//1.获取所有public的成员变量Field[] fields=cls.getFields();
for (Fieldfield:fields) {
System.out.println(field);
        }
//2.获取指定名字的public成员变量Fielda=cls.getField("a");
Studentstudent=newStudent();
//3.操作Field的方法,get和setSystem.out.println(a.get(student));
a.set(student,10);
System.out.println(student);
//4.获取所有成员变量Field[] declaredFields=cls.getDeclaredFields();
for (Fieldf : declaredFields) {
System.out.println(f);
        }
    }
}

这里的两个操作Field的方法只能操作public修饰的变量,如果需要访问其他修饰符修饰的元素,则要添加安全许可:


a.setAccessible(true);

2.1 获取构造方法


Constructor<T>getConstructor(Class<?>... parameterTypes)  //根据参数不同获取指定的public构造方法Constructor<?>[] getConstructors()  //获取所有public构造方法Constructor<T>getDeclaredConstructor(Class<?>... parameterTypes) //根据参数不同获取指定的构造方法Constructor<?>[] getDeclaredConstructors() //获取所有构造方法

2.2 操作构造方法


T newInstance(Object... initargs)  //创建对象

通过代码演示其中一两种操作:


public class reflectTest2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class cls = Class.forName("com.sdxb.reflect.Student");
        //有参构造方法
        Constructor constructor = cls.getConstructor(String.class, int.class, int.class);
        Object student = constructor.newInstance("sdxb", 24, 1);
        System.out.println(student);
        //无参构造方法
        Constructor constructor2 = cls.getConstructor();
        Object student2 = constructor2.newInstance();
        System.out.println(student2);
        //无参构造方法可以用下面的方式代替
        cls.newInstance();
    }
}

3.1 获取成员方法


Method getMethod(String name, Class<?>... parameterTypes) //根据名称和参数类型获取public方法
Method[] getMethods()  //获取所有public方法
Method getDeclaredMethod(String name, Class<?>... parameterTypes) //根据名称和参数类型获取方法
Method[] getDeclaredMethods()  //获取所有方法

3.2 成员方法的操作


Object invoke(Object obj, Object... args)  //执行成员方法

为了方便测试,我为Student类增加了两个成员方法:


public void run(){
    System.out.println("run");
}
public void run(int speed){
    System.out.println("run"+speed);
}

接着对成员方法的反射进行测试:


publicclassreflectTest3 {
publicstaticvoidmain(String[] args) throwsNoSuchMethodException, InvocationTargetException, IllegalAccessException {
Classcls=Student.class;
Studentstudent=newStudent();
//无参方法Methodrun=cls.getMethod("run");
run.invoke(student);
//带参数方法Methodrun2=cls.getMethod("run", int.class);
run.invoke(student,1);
    }
}

(四)总结


java的反射机制在框架中应用十分广泛,被誉为是框架的灵魂。原因是框架是一个半成品,我们无法通过new去创建框架中定义的类,因此反射起到了很大的作用。

相关文章
|
5天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
18 2
|
10天前
|
Java 编译器
探索Java中的异常处理机制
【10月更文挑战第35天】在Java的世界中,异常是程序运行过程中不可避免的一部分。本文将通过通俗易懂的语言和生动的比喻,带你了解Java中的异常处理机制,包括异常的类型、如何捕获和处理异常,以及如何在代码中有效地利用异常处理来提升程序的健壮性。让我们一起走进Java的异常世界,学习如何优雅地面对和解决问题吧!
|
21天前
|
XML 安全 Java
Java反射机制:解锁代码的无限可能
Java 反射(Reflection)是Java 的特征之一,它允许程序在运行时动态地访问和操作类的信息,包括类的属性、方法和构造函数。 反射机制能够使程序具备更大的灵活性和扩展性
34 5
Java反射机制:解锁代码的无限可能
|
9天前
|
Java 数据库连接 开发者
Java中的异常处理机制及其最佳实践####
在本文中,我们将探讨Java编程语言中的异常处理机制。通过深入分析try-catch语句、throws关键字以及自定义异常的创建与使用,我们旨在揭示如何有效地管理和响应程序运行中的错误和异常情况。此外,本文还将讨论一些最佳实践,以帮助开发者编写更加健壮和易于维护的代码。 ####
|
15天前
|
安全 IDE Java
Java反射Reflect机制详解
Java反射(Reflection)机制是Java语言的重要特性之一,允许程序在运行时动态地获取类的信息,并对类进行操作,如创建实例、调用方法、访问字段等。反射机制极大地提高了Java程序的灵活性和动态性,但也带来了性能和安全方面的挑战。本文将详细介绍Java反射机制的基本概念、常用操作、应用场景以及其优缺点。 ## 基本概念 ### 什么是反射 反射是一种在程序运行时动态获取类的信息,并对类进行操作的机制。通过反射,程序可以在运行时获得类的字段、方法、构造函数等信息,并可以动态调用方法、创建实例和访问字段。 ### 反射的核心类 Java反射机制主要由以下几个类和接口组成,这些类
34 2
|
20天前
|
存储 缓存 安全
🌟Java零基础:深入解析Java序列化机制
【10月更文挑战第20天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
22 3
|
20天前
|
安全 Java UED
深入理解Java中的异常处理机制
【10月更文挑战第25天】在编程世界中,错误和意外是不可避免的。Java作为一种广泛使用的编程语言,其异常处理机制是确保程序健壮性和可靠性的关键。本文通过浅显易懂的语言和实际示例,引导读者了解Java异常处理的基本概念、分类以及如何有效地使用try-catch-finally语句来处理异常情况。我们将从一个简单的例子开始,逐步深入到异常处理的最佳实践,旨在帮助初学者和有经验的开发者更好地掌握这一重要技能。
20 2
|
22天前
|
存储 运维 Java
💻Java零基础:深入了解Java内存机制
【10月更文挑战第18天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
27 1
|
16天前
|
Java 开发者
深入理解Java异常处理机制
【10月更文挑战第29天】在Java的世界中,异常处理如同生活的调味品,不可或缺。它确保了程序在遇到错误时不会崩溃,而是优雅地继续运行或者给出提示。本文将带你领略异常处理的奥秘,从基础的try-catch语句到高级的自定义异常,让你在面对程序中的各种“意外”时,能够从容应对。
|
18天前
|
SQL Java
探索Java中的异常处理机制
【10月更文挑战第26天】 在本文中,我们将深入探讨Java编程语言的异常处理机制。通过分析不同类型的异常、异常的捕获与抛出方式,以及如何自定义异常类,读者将能够更好地理解并应用Java中的异常处理机制来提高代码的健壮性和可读性。
23 0