Java基础教程:反射基础
Java基础教程:反射基础
引入反射
反射是什么
能够动态分析类能力的程序称为反射。反射是一种很强大且复杂的机制。
Class类
在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时的类型标识。这个对象追踪着每个对象所属的类。虚拟机利用运行时类的信息选择相应的方法执行。
我们可以通过专门的Java类访问这些信息。保存这些信息的类称为Class。
直接获取
Class cl1 =Date.class;
Class cl2 = Integer.class;
根据对象获得类信息
MyClass myClass;
.....
Class cl = myClass.getClass();
cl.getName(); //获得类名
调用静态方法forName获得类名相应的Class对象。
String className = 'java.util.Date';
Class cl = Class.forName(className);
注意:
虚拟机为每一个类型管理一个Class对象。因此使用==可以实现两个类对象比较的操作。
利用反射分析类的能力
API函数举例
- getDeclaredFields():获得此类对象所表示的类或接口所声明的所有字段。
- getFields():输出类以及其所继承的父类的
public
字段 - getDeclaredMethods():获得此类对象所表示的类或接口所声明的所有方法,包括公共、保护、私有但不包括继承。
getDeclaredConstructors()
:返回Constructor
对象的一个数组,这些对象反映此Class
对象表示的类声明的所有构造方法。- getName():获得此class所表示实体的名称。
示例:输出字段
GetFields只会输出publicStr,GetDeclaredFields则会忽略访问控制符输出所有字段!
public class MyClass{
public String publicStr;
private String privateStr;
protected String protectedStr;
public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class;
//调用GetFields()
for(Field field : c1.getFields()){
System.out.println(field.getName());
}
System.out.println("=============");
//调用GetDeclaredFields()
for(Field field : c1.getDeclaredFields()){
System.out.println(field.getName());
}
}
}
示例:输出方法
getDeclaredMethods只会输出本类的所有方法!
public class MyClass{
public void publicFun(int a){}
private void privateFun(int a){}
protected void protectFun(int a){}
public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class;
//2.1 获取所有 public 访问权限的方法
//包括自己声明和从父类继承的
//Method[] mMethods = c1.getMethods();
//2.2 获取所有本类的的方法(不问访问权限)
Method[] mMethods = c1.getDeclaredMethods();
//3.遍历所有方法
for (Method method :
mMethods) {
//获取并输出方法的访问权限(Modifiers:修饰符)
int modifiers = method.getModifiers();
System.out.print(Modifier.toString(modifiers) + " ");
//获取并输出方法的返回值类型
Class returnType = method.getReturnType();
System.out.print(returnType.getName() + " "
+ method.getName() + "( ");
//获取并输出方法的所有参数
Parameter[] parameters = method.getParameters();
for (Parameter parameter :
parameters) {
System.out.print(parameter.getType().getName()
+ " " + parameter.getName() + ",");
}
//获取并输出方法抛出的异常
Class[] exceptionTypes = method.getExceptionTypes();
if (exceptionTypes.length == 0) {
System.out.println(" )");
} else {
for (Class c : exceptionTypes) {
System.out.println(" ) throws "
+ c.getName());
}
}
}
}
}
调用getDeclaredMethods输出结果:
- public static void main( [Ljava.lang.String; arg0, )
- protected void protectFun( int arg0, )
- private void privateFun( int arg0, )
- public void publicFun( int arg0, )
调用getMethods输出结果:
- public static void main( [Ljava.lang.String; arg0, )
- public void publicFun( int arg0, )
- public final void wait( ) throws java.lang.InterruptedException
- public final void wait( long arg0,int arg1, ) throws java.lang.InterruptedException
- public final native void wait( long arg0, ) throws java.lang.InterruptedException
- public boolean equals( java.lang.Object arg0, )
- public java.lang.String toString( )
- public native int hashCode( )
- public final native java.lang.Class getClass( )
- public final native void notify( )
- public final native void notifyAll( )
在运行时使用反射分析对象
API函数举例
- setAccessible(boolean flag):为反射对象设置可访问标志。为true使得对象的私有属性也可以被查询和设置。
- getField(): 返回一个
Field
对象,它反映此Class
对象所表示的类或接口的指定公共成员字段。 - get(Object obj):返回对象中用Field对象表示的域值。
- set(Object obj,Object newValue):用一个新值设置Obj对象中的Field对象表示的域。
示例:获取并设置对象的私有字段值
public class MyClass{
private String context = "Hello World";
public static void main(String[] args) {
//获取Class类
Class c1 = MyClass.class;
try {
//构建对象
Object myClass = c1.newInstance();
//获取私有变量
Field context = c1.getDeclaredField("context");
//获取私有变量访问权
context.setAccessible(true);
//访问私有变量值
System.out.println(context.get(myClass));
//设置私有变量值
context.set(myClass, "Hi Boy!");
System.out.println(context.get(myClass));
} catch (Exception e) {
e.printStackTrace();
}
}
}
利用反射调用任意方法
API函数说明
public Object invoke(Object obj,Object... args)
- 参数:
obj
- 从中调用底层方法的对象args
- 用于方法调用的参数 - 返回:使用参数
args
在obj
上指派该对象所表示方法的结果
示例:调用私有方法
public class NCConfgCliService {
private void privateFun(int a){
System.out.println(a);
}
public static void main(String[] args) {
//获取Class类
Class c1 = NCConfgCliService.class;
try {
//获取私有方法
Method privateMethod = c1.getDeclaredMethod("privateFun",int.class);
//创建类的实例
Object obj = c1.newInstance();
//调用私有方法
privateMethod.invoke(obj,10);
} catch (Exception e) {
e.printStackTrace();
}
}
}