Java 基础 - 反射

本文详细介绍了Java反射机制,包括基本概念、获取Class对象的三种方式、java.lang.reflect包中的核心类如Constructor、Method、Field等的使用,以及访问构造方法、方法和成员变量的方法。此外,还探讨了注解的访问和泛型在反射中的应用,如获取泛型方法的返回类型和参数类型。文章最后提到了动态类加载、动态代理等高级技术。
摘要由CSDN通过智能技术生成

目录

一、Java反射机制是什么?

1.1 基本概念

1.2 使用主要种类

二、常用API

2.1 java.lang.Class 类

2.1.1 获取class对象的三种方式

2.2 java.lang.reflect包

2.3 访问构造方法

Modifier类的常用静态方法

获取Constructor对象

构造方法参数

利用Constructor对象实例化一个类

2.4 访问方法(获取方法)

Method类的常用方法

获取Method对象

方法参数以及返回类型

通过Method对象调用方法

2.5 访问成员变量

Field类的常用方法

获取Field对象

变量名称

变量类型

获取或设置(get/set)变量值

2.6 注解

简介

类注解

方法注解

参数注解

变量注解

2.7 泛型

运用泛型反射的经验法则

泛型方法返回类型

泛型方法参数类型

泛型变量类型

2.8 数组

java.lang.reflect.Array

高级技术

动态类的加载和重载

动态代理简介

反射调用流程小结

 


一、Java反射机制是什么?

1.1 基本概念

Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在Java中,只要给定类的名字,就可以通过反射机制来获得类的所有信息。Java反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包。

  • 在运行时判断任意一个对象所属的类。
  • 在运行时构造任意一个类的对象。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时调用任意一个对象的方法。
  • 生成动态代理。

要想知道一个类的属性和方法,必须先获取到该类的字节码文件对象。获取类的信息时,使用的就是Class类中的方法。所以先要获取到每一个字节码文件(.class)对应的Class类型的对象.

Java反射机制的优缺点

优点:

  • 能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
  • Java动态编译相结合,可以实现无比强大的功能。
  • 对于Java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

缺点:

  • 反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
  • 反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。

1.2使用主要种类

与Java-Reflection相关种类主要分为:

类名 用途
Class类 代表类的实体,在运行的Java应用程序中表示类和接口
Field类 代表类的成员变量(成员变量也称为类的属性)
Method类 代表类的方法
Constructor类 代表类的构造方法
Annotation类 代表类的注解

二、常用API

实现java反射机制的类都位于java.lang.reflect包中,java.lang.Class类是Java反射机制API中的核心类。

2.1 java.lang.Class 类

java.lang.Class类是实现反射的关键所在,Class类的一个实例表示Java的一种数据类型,包括类、接口、枚举、注解(Annotation)、数组、基本数据类型和voidClass没有公有的构造方法,Class实例是由JVM在类加载时自动创建的。

在程序代码中获得Class实例可以通过如下代码实现:

// 1. 通过类型class静态变量
Class clz1 = String.class;
String instance1 = clz1.newInstance();
// 2. 通过对象的getClass()方法
String str2 = "Hello";
Class clz2 = str2.getClass();
String instance2 = clz2.newInstance();
//

每一种类型包括类和接口等,都有一个class静态变量可以获得Class实例。另外,每一个对象都有getClass()方法可以获得Class实例,该方法是由Object类提供的实例方法。

2.1.1 获取class对象的三种方式

  • Object类的getClass()方法
  • 静态属性class
  • Class类中的静态方法forName()

2.2 java.lang.reflect包

java.lang.reflect包提供了反射中用到类,主要的类说明如下:

  • Constructor类:提供类的构造方法信息。
  • Field类:提供类或接口中成员变量信息。
  • Method类:提供类或接口成员方法信息。
  • Array类:提供了动态创建和访问Java数组的方法。
  • Modifier类:提供类和成员访问修饰符信息。

2.3 访问构造方法

为了能够动态获取对象构造方法的信息,首先需要通过下列方法之一创建一个Constructor类型的对象或者数组。

  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>...parameterTypes)

创建的每个Constructor对象表示一个构造方法,然后利用Constructor对象的方法操作构造方法。

getConstructors()和getDeclaredConstructors()区别
getConstructors():获得某个类的所有的公共(public)的构造方法,包括父类中的构造方法。
getDeclaredConstructors():获得某个类的所有声明的构造方法,即包括public、private和proteced,但是不包括父类的申明构造方法。
同样类似的还有getMethods()和getDeclaredMethods()。

Constructor类的常用方法

方法名称 说明
isVarArgs() 查看该构造方法是否允许带可变数量的参数,如果允许,返回true,否则返回false
getParameterTypes() 按照声明顺序以Class数组的形式获取该构造方法各个参数的类型

通过java.lang.reflect.Modifier类可以解析出getMocMers()方法的返回值所表示的修饰符信息。在该类中提供了一系列用来解析的静态方法,既可以查看是否被指定的修饰符修饰,还可以字符串的形式获得所有修饰符。

Modifier类的常用静态方法

静态方法名称 说明
isStatic(int mod) 如果使用 static 修饰符修饰则返回 true,否则返回 false
isPublic(int mod) 如果使用 public 修饰符修饰则返回 true,否则返回 false
isProtected(int mod) 如果使用 protected 修饰符修饰则返回 true,否则返回 false
isPrivate(int mod) 如果使用 private 修饰符修饰则返回 true,否则返回 false
isFinal(int mod) 如果使用 final 修饰符修饰则返回 true,否则返回 false
toString(int mod) 以字符串形式返回所有修饰符

获取Constructor对象

我们可以通过Class对象来获取Constructor类的实例:

Class aClass = ...//获取Class对象
Constructor[] constructors = aClass.getConstructors();

返回的Constructor数组包含每一个声明为公有的(Public)构造方法。
如果你知道你要访问的构造方法的方法参数类型,你可以用下面的方法获取指定的构造方法,这例子返回的构造方法的方法参数为String类型:

Class aClass = ...//获取Class对象
Constructor constructor = aClass.getConstructor(new Class[]{String.class});

如果没有指定的构造方法能满足匹配的方法参数则会抛出:NoSuchMethodException

构造方法参数

你可以通过如下方式获取指定构造方法的方法参数信息:

Constructor constructor = ... //获取Constructor对象
Class[] parameterTypes = constructor.getParameterTypes();

利用Constructor对象实例化一个类

你可以通过如下方法实例化一个类:

Constructor constructor = MyObject.class.getConstructor(String.class);
MyObject myObject = (MyObject)constructor.newInstance("constructor-arg1");

constructor.newInstance()方法的方法参数是一个可变参数列表,但是当你调用构造方法的时候你必须提供精确的参数,即形参与实参必须一一对应。在这个例子中构造方法需要一个String类型的参数,那我们在调用newInstance方法的时候就必须传入一个String类型的参数。

2.4 访问方法(获取方法)

动态获取一个对象方法的信息,首先需要通过下列方法之一创建一个Method类型的对象或者数组。

  • getMethods()
  • getMethods(String name,Class<?> …parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethods(String name,Class<?>...parameterTypes)

Method类的常用方法

静态方法名称 说明
getName() 获取该方法的名称
getParameterType() 按照声明顺序以 Class 数组的形式返回该方法各个参数的类型
getReturnType() 以 Class 对象的形式获得该方法的返回值类型
getExceptionTypes() 以 Class 数组的形式获得该方法可能抛出的异常类型
invoke(Object obj,Object...args) 利用 args 参数执行指定对象 obj 中的该方法,返回值为 Object 类型
isVarArgs() 查看该方法是否允许带有可变数量的参数,如果允许返回 true,否则返回 false
getModifiers() 获得可以解析出该方法所采用修饰符的整数

获取Method对象

可以通过Class对象获取Method对象,如下例:

Class aClass = ...//获取Class对象
Method[] meth
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiarBoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值