内容简介:Java反射详解
反射是指程序在运行时能够获取自身的信息. Java的反射机制将类和方法封装为对象, 允许程序动态的创建对象或调用方法.
获得Class对象
java.lang.Class
是反射机制的核心封装类, 通常有三种方法可以获得类的 Class
对象.
为了便于说明创建一个 Item
类:
class Item {
publicstaticvoidmain(String[] args) {
Item item = new Item();
}
}
-
Class.forName("Item"): 根据目标类的名称获得Class对象的静态方法. -
Item.class: 通过静态属性获得Class对象 -
item.getClass(): 通过实例方法获得Class对象
通过 Class
对象可以访问类的元信息:
-
String getName(): 获得包含包名在内的完整类名 -
String getSimpleName(): 获得不含包名的简单类名 -
Package getPackage(): 获得包的封装对象 -
Class getSuperclass(): 获得父类的Class对象 -
Class[] getInterfaces(): 获得所有实现接口的Class对象
获得构造器
通过 Class
对象调用默认构造器进行实例化:
public class Main {
publicstaticvoidmain(String[] args)
throws InstantiationException, IllegalAccessException {
Class clazz = MyClass.class;
MyClass obj = (MyClass) clazz.newInstance();
System.out.println(obj.i);
}
}
不过这样只能调用默认构造器, 若要使用其它构造器实例化则需要先获得构造器对象:
-
Constructor clazz.getConstructor(Class[]): 根据参数获得public构造器对象. -
Constructor clazz.getDeclaredConstructor(Class[]): 根据参数获得构造器对象, 包括public,default,protected,private.
也可以通过 Class
对象获得构造器的列表:
-
Constructor[] clazz.getConstructors(): 获得所有public构造器对象. -
Constructor[] clazz.getDeclaredConstructors(): 获得所有构造器对象, 包括public,default,protected,private.
Constructor.newInstance()
方法可以用于实例化类. 示例:
Constructor constructor = MyClass.class.getConstructor(String.class);
MyClass obj = (MyClass)constructor.newInstance("abc");
获得方法
可以同通过 Class
对象获得 Method
对象访问类的方法:
public class Item {
publicvoidtest(String string) {
System.out.println(string);
}
publicstaticvoidmain(String[] args) throws Exception {
Item item = new Item();
Method method = Item.class.getMethod("test", String.class);
method.invoke(item, "Hello World");
}
}
getMethod()
第一个参数为方法的名称, 后面的可变参数表示目标方法的参数表. 两者共同标记类中的一个方法.
invoke()
方法第一个参数为调用方法的实例, 后面为方法的实参表.
访问无参数的方法也很简单:
public class Item {
publicvoidtest() {
System.out.println("Hello World");
}
publicstaticvoidmain(String[] args) throws Exception {
Item item = new Item();
Method method = Item.class.getMethod("test", null);
method.invoke(item);
}
}
有两个方法用于获得方法:
-
Method getMethod(name, clazz...): 根据名称和参数表获得public方法, 包括继承自父类的方法. -
Method getDeclaredMethod(name, clazz...): 根据名称和参数表获得方法, 包括继承自父类的方法. 包括public,default,protected,private.
类似地, 有两个方法用于获得方法列表:
-
Method[] getMethods(): 获得所有public方法 -
Method[] getDeclaredMethods(): 获得所有方法
int Method.getModifiers()
用于获得 public
, static
等修饰符. 修饰符由标志位(BitSet)标示, 被转换成int返回.
可以使用 java.lang.reflect.Modifier
检查标志符类型:
Modifier.isAbstract(int modifiers); Modifier.isFinal(int modifiers); Modifier.isInterface(int modifiers); Modifier.isNative(int modifiers); Modifier.isPrivate(int modifiers); Modifier.isProtected(int modifiers); Modifier.isPublic(int modifiers); Modifier.isStatic(int modifiers); Modifier.isStrict(int modifiers); Modifier.isSynchronized(int modifiers); Modifier.isTransient(int modifiers); Modifier.isVolatile(int modifiers);
直接调用私有方法Method对象的 invoke
方法时会抛出 IllegalAccessException
异常, 需要先调用 method.setAccessible(true)
:
class Item {
privatevoidtest(String string) {
System.out.println(string);
}
}
public class Main {
publicstaticvoidmain(String[] args) throws Exception {
Item item = new Item();
Method method = Item.class.getDeclaredMethod("test", String.class);
method.setAccessible(true); // 未加此行会抛出IllegalAccessException
method.invoke(item, "Hello World");
}
}
获得域
访问域与访问方法非常类似:
-
Field getField(name): 根据名称获得域, 包括继承自父类的方法. -
Field getDeclaredField(name): 根据名称获得域, 包括继承自父类的域. 包括public,default,protected,private. -
Field[] getFields(): 获得所有public域 -
Field[] getDeclaredFields(): 获得所有域
访问私有域同样需要 setAccessible(true)
.
Field
对象可以访问或修改域:
class Item {
private String msg;
}
public class Main {
publicstaticvoidmain(String[] args) throws Exception {
Item item = new Item();
Field field = Item.class.getDeclaredField("msg");
field.setAccessible(true);
field.set(item, "Hello World");
System.out.println((String)field.get(item));
}
}
反射与泛型
Java的反射机制允许在运行时获得泛型参数, 需要获得泛型参数的场景有:
-
获得泛型域的类型, 以进行访问或设置
-
获得泛型方法(构造器)的参数类型, 以进行调用
-
获得泛型方法的返回值类型
java.lang.reflect.Type
接口用于描述泛型参数, Type
接口的唯一实现是 Class
类.
获得域的类型:
public class Item {
public List<String> list;
publicstaticvoidmain(String[] args) throws Exception {
Field field = Item.class.getField("list");
Type type = field.getGenericType();
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
Type[] typeArgs = paramType.getActualTypeArguments();
for(Type typeArg : typeArgs){
Class typeArgClass = (Class) typeArg;
System.out.println(typeArgClass);
}
}
}
}
获得泛型方法参数类型:
public class Item {
public List<String> list;
public List<String> getList() {
return list;
}
publicstaticvoidmain(String[] args) throws Exception {
Method method = Item.class.getMethod("getList", null);
Type type = method.getGenericReturnType();
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
Type[] typeArgs = paramType.getActualTypeArguments();
for(Type typeArg : typeArgs){
Class typeArgClass = (Class) typeArg;
System.out.println(typeArgClass);
}
}
}
}
获得泛型方法的返回值类型:
public class Item {
public List<String> list;
public List<String> getList() {
return list;
}
publicstaticvoidmain(String[] args) throws Exception {
Method method = Item.class.getMethod("getList", null);
Type type = method.getGenericReturnType();
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
Type[] typeArgs = paramType.getActualTypeArguments();
for(Type typeArg : typeArgs){
Class typeArgClass = (Class) typeArg;
System.out.println(typeArgClass);
}
}
}
}
本文永久更新链接地址 : http://www.linuxidc.com/Linux/2018-01/150359.htm
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 详解 .NET 反射中的 BindingFlags 以及常用的 BindingFlags 使用方式
- Go语言反射之反射调用
- Go语言反射之类型反射
- Go语言反射之值反射
- 模块讲解----反射 (基于web路由的反射)
- 装饰器与元数据反射(4)元数据反射
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。