Files
rikako-note/java se/反射.md
2023-05-08 00:12:58 +08:00

8.0 KiB
Raw Permalink Blame History

反射

Class对象

Class对象用于访问类信息想要获取class对象可以通过如下方法

获取Class对象方法

调用实例的getClass方法

Random generator = new Random():
Class cl = generator . getClass () ;
String name = cl.getName() ; // name is set to "java . util . Random"

调用Class类的静态方法forName方法

String dassName = " java . util . Random" ;
Class cl = Class.forName ( dassName ) ;

通过T.class获取

如果T是一个java类型那么T.class代表T类型对应的Class对象

Class dl = Random.class; 
Gass cl 2 = int.class ;
Class cl 3 = Double[].class ;

Class对象表示的是一个类型而类型不一定是类也包含基本类型如int,long等。

Class对象的比较

JVM为每个类型只维护一个Class对象故而不同的Class之间可以通过==符号进行比较

ife.getClass()==Employee.class)

通过Class对象创建新实例

下述示例创建了一个与e具有相同类型的实例newInstance方法默认会调用默认构造函数如果该类型没有默认构造函数会抛出一个checked exception

e.getClass().newInstance()

如果将forName和newInstance方法结合起来使用可以根据存储在字符串中的类型动态创建一个对象

String driverClassName = "com.mysql.cj.jdbc.Driver";
Class.forName(driverClassName).newInstance();

使用反射分析类

java.lang.reflect类中含有三个类

  • Field用于描述类的域
  • Method用于描述类的方法
  • Constructor用于描述类的构造器

Field.getType

Field类有一个getType方法返回值是域所属类型的Class对象。

获取类的域、方法和构造器

Class.getFields

返回值为类的public域包含从父类继承的public域

Class.getDeclaredFields

返回类中声明的所有域包含为private和protected的域但是不包含从父类继承的域

Class.getMethods

返回值为类提供的public方法包含从父类继承的public方法

Class.getDeclaredMethods

返回类中声明的所有方法包含private方法和protected方法但是不包含从父类继承的方法

Class.getConstructors

只能获取到public构造器

Class.getDeclaredConstructors

能获取到所有的构造器包含private和protected构造器

Method、Field、Constructor中的方法

getDeclaringClass

返回定义该方法、域、构造器类型的Class对象

Class getDeclaringClass()

getExceptionTypesMethod和Constructor中包含

返回方法抛出的异常类型的数组

Class[] getExceptionTypes()

getModifiers

返回一个描述Field、Method、Constrcutor的修饰符的整数类型不同的位描述不同的修饰符状态如public、static、是否抽象类、是否接口等

int getModifiers()

getName

返回描述Field、Constructor、Method的字符串

String getName()

getParameterTypes(Method和Constructor中包含)

返回一个Class数组用于描述参数类型

Class[] getParameterTypes()

getReturnType(只在Method方法中包含)

返回Method的返回类型

Class getReturnType()

Modifier中的方法

toString

该静态方法将modifiers整数中的修饰符内容转化为字符串

static String toString(int modifiers)

isAbstract

static boolean isAbstract(int modifiers)

isFinal

static boolean isFinal(int modifiers)

isInterface

static boolean isInterface(int modifiers)

isNative

static boolean isNative(int modifiers)

isPrivate

static boolean isPrivate(int modifiers)

isProtected

static boolean isProtected(int modifiers)

isPublic

static boolean isPublic(int modifiers)

isStatic

static boolean isStatic(int modifiers)

isSynchronized

static boolean isSynchronized(int modifiers)

isVolatile

static boolean isVolatile(int modifiers)

使用反射分析类的内容

如果在运行时有一个Field对象和一个类实例obj想要查看obj实例中Field对应域的值可以使用如下方式

f.get(obj);

但是如果Field的modifiers显示该Field是private的那么f.get(obj)方法将会抛出一个IllegalAccessException。
此时,可以通过f.setAccessible(true)来访问private域中的内容。

f.setAccessible(true);
Object v = f.get(obj);

设置Field的值则是可以通过f.set(obj,value)来实现。

f.setAccessible(true);
f.setValue(obj,"shiro");

AccessibleObject

Field,Method,Constructor类型都拥有公共的父类AccessibleObject

setAccessible

void setAccessible(boolean flag);

// 批量设置可访问状态
static void setAccessible(AccessibleObject[] array,boolean flag);

isAccessible

boolean isAccessible();

使用反射调用方法

Method类中提供了一个invoke方法来调用Method所表示的方法Method.invoke方法签名如下:

Object invoke(Object obj,Object... args)

obj表示调用方法的对象args表示参数数组。

如果Method位静态方法那么obj应该传入null

如果Method代表的方法返回的是一个基本类型那么invoke方法会返回器包装类型int->Integer.

Method.getMethod

如果想要根据方法名称和参数类型来获取Class对象中的Method可以调用如下方法

Method getMethod(String name,Class... parameterTypes)

示例如下:

Method ml = Employee. class.getMethod ( "getName") ;
Method m2 = Employee.class.getMethod ( "raiseSalary" , double.class) ;