Java 反射-访问成员
反射定义了一个接口java.lang.reflect.Member 其实现有java.lang.reflect.Field,java.lang.reflect.Method,以及 java.lang.reflect.Constructor。分别定义了如何来访问字段,方法以及构造器的实现。
一、访问字段
获取字段的类型:字段类型可以是8种基本数据类型,引用类型和枚举类型。
/**
* 访问字段的类型
*/
@Test
public void testType() throws Exception {
c = Class.forName("cn.com.xiaofen.field.FieldT");
/* 根据字段名臣获取Field对象 */
Field field = c.getField("val");
/* 打印字段的类型 */
out.format("%s%n", field.getType());
/* 字段的标准类型 */
out.format("%s%n", field.getGenericType());
}
检索和访问方法的修饰符:字段可能出现的修饰符。
· Access modifiers: public, protected, and private
· Field-specific modifiers governing runtime behavior: transient and volatile
· Modifier restricting to one instance: static
· Modifier prohibiting value modification: final
· Annotations
/**
* 检索和访问方法的修饰符
*/
@Test
public void testModifiers() throws ClassNotFoundException, NoSuchFieldException, SecurityException {
c = Class.forName("cn.com.xiaofen.field.FieldT");
/* 根据字段名臣获取Field对象 */
Field field = c.getField("NAME");
/* 获取字段的访问修饰符 */
int mod = field.getModifiers();
out.println(Modifier.toString(mod));
/*字段查找参考官方API*/
}
获取和设置字段的值:给定一个Class对象的实例可以通过反射获取字段的值,只有在特殊情况下使用,其违反了类的设计原则。
/**
* 获取和设置字段的值
* */
@Test
public void testValue() throws Exception{
FieldT<Object> fieldT=new FieldT<>();
c = fieldT.getClass();
/*获取字段对象*/
Field field=c.getDeclaredField("age");
/*为字段设置值*/
field.setInt(fieldT, 100);
/*获取字段的值*/
out.println(field.getInt(fieldT));
}
二、访问方法
获取方法信息:方法的类型信息包括名字,修饰符,参数,返回类型及异常列表等。
/**
* 访问方法信息
*/
@Test
public void testInfo() throws Exception {
FieldT<Object> fieldT = new FieldT<>();
c = fieldT.getClass();
/* 获取所有方法并遍历 */
Method[] allMethods = c.getDeclaredMethods();
for (Method m : allMethods) {
out.format("%s%n", m.toGenericString());
/* 打印方法类型 */
out.format(fmt, "ReturnType", m.getReturnType());
out.format(fmt, "GenericReturnType", m.getGenericReturnType());
/* 获取参数类型 */
Class<?>[] pType = m.getParameterTypes();
Type[] gpType = m.getGenericParameterTypes();
/* 打印参数类型 */
for (int i = 0; i < pType.length; i++) {
out.format(fmt, "ParameterType", pType[i]);
out.format(fmt, "GenericParameterType", gpType[i]);
out.format(fmt, "GenericParameterName", gpType[i]);
}
/* 获取异常类型 */
Class<?>[] xType = m.getExceptionTypes();
Type[] gxType = m.getGenericExceptionTypes();
for (int i = 0; i < xType.length; i++) {
out.format(fmt, "ExceptionType", xType[i]);
out.format(fmt, "GenericExceptionType", gxType[i]);
}
/* 打印方法参数数量 */
out.format(fmt, "ParamCount", m.getParameterCount());
/* 打印方法参数名称 */
Parameter[] param = m.getParameters();
for (Parameter p : param) {
out.format(fmt, "ParameterName", p.getName());
}
/* 解析方法修饰符 */
out.format(" Modifiers: %s%n", Modifier.toString(m.getModifiers()));
}
}
调用方法:反射提供了一种方法用来调用Class对象的方法。java.lang.reflect.Method.invoke()。
/**
* 调用方法
* */
@Test
public void testInvoke() throws Exception{
FieldT<Object> fieldT = new FieldT<>();
c = fieldT.getClass();
/*获取指定方法*/
Method method =c.getMethod("setSex", String.class);
/*调用方法*/
method.invoke(fieldT, "hello");
out.format(" result: %s%n", fieldT.getSex());
}
三、构造器
构造器信息:构造器信息包括名称、修饰符、参数、异常列表等。
/**
* 访问构造器的基本信息
*/
@Test
public void testFind() throws Exception {
c = Class.forName("cn.com.xiaofen.modifier.Hello");
/* 获取所有可用构造器 */
Constructor[] allConstructors = c.getDeclaredConstructors();
for (Constructor ctor : allConstructors) {
/* 获取并打印参数类型 */
Type[] pType = ctor.getGenericParameterTypes();
for (int i = 0; i < pType.length; i++) {
out.format("GenericParameterType %s%n", pType[i]);
}
/* 打印构造器访问修饰符 */
out.format("modifier: %s%n", Modifier.toString(ctor.getModifiers()));
out.println("-------------");
}
}
创建一个新的实例:反射提供了两个方法用来创建新的Class实例,java.lang.reflect.Constructor.newInstance() andClass.newInstance()前者为首选,原因如下。
Class.newInstance(),只能调用无参构造器。
Class.newInstance()在构造器中抛出任何异常,无论检查与否。Constructor.newInstance()总是抛出InvocationTargetException包装的异常。
Class.newInstance()构造器必须是可见的,Constructor.newInstance()某些情况下可以调用私有的构造器。
/**
* 实例化对象
* */
@Test
public void testNewInstance() throws Exception {
c = Class.forName("cn.com.xiaofen.modifier.Hello");
/*获取一个String类型的构造器*/
Constructor<?> constructor=c.getConstructor(String.class);
/*使用有参数构造器实例化对象*/
Hello<?, ?> hello=(Hello<?, ?>) constructor.newInstance("hello");
out.println(hello.getMessage());
/*使用无参数构造器实例化对象*/
hello=(Hello<?, ?>) c.newInstance();
out.println(hello.getMessage());
}
项目地址:https://github.com/poai/Reflect.git