8.0 KiB
- 反射
反射
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之间可以通过==符号进行比较
if(e.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()
getExceptionTypes(Method和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) ;