反射,总而言之当初我字面上并没看明白什么意思。个人认为“反射”名字取得不够好,应该叫Java选择机制
就像jQuery选择器一样,能够在运行过程中获取dom节点的所有信息。
java反射机制也是一样,就是说能在程序运行过程中获取和调用任意一个类的所有方法属性。
java中已经提供了专门处理反射的包java.lang.reflect
下面就先说说类对象
例1:类对象创建的三个方法
LoadClass.java
package com.zero;
public class LoadClass {
public static void main(String [] args) throws ClassNotFoundException {
/*
* 类对象创建的三种方法(类对象都是Class的实例)
*/
Class t1 = null;
Class t2 = null;
Class t3 = null;
t1 = Class.forName("com.zero.Test");
t2 = new Test().getClass();
t3 = Test.class;
}
}
//测试类
class Test {
//静态语句块,类加载时运行,只运行一次
static{
System.out.println("类加载中");
}
}
例1运行结果:类加载中
以上类对象创建的方法中,最常用的是Class.forName("xxx")这种方法,一般jdbc连接数据库加载jdbc驱动使用的就是这个方法。
进入正题吧,如下案例
例2:java反射机制
ReflectTest.java
package com.zero;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class ReflectTest {
public static void main(String [] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class test2 = Class.forName("com.zero.TestReflect");//类对象创建
TestReflect tt = (TestReflect)test2.newInstance();//实例化testReflect对象
Method [] methods = test2.getMethods();//获取类对象成员方法
System.out.println("---------类成员方法如下-------------");
for(Method m:methods){
int mo = m.getModifiers();//获取方法修饰符,这里获取的是int类型,需要使用Modifier.toString()转换
System.out.print(Modifier.toString(mo) + " ");
System.out.print(m.getReturnType().getName()+" ");//方法发返回类型
System.out.print(m.getName());//方法名
Class [] parameters = m.getParameterTypes();//方法的所有参数类型
System.out.print("(");
int i = 0;
for(Class parameter:parameters){
System.out.print(parameter.getName()+" " + "arg" + i++);
if(i < parameters.length) {
System.out.print(", ");
}
}
System.out.println("){}");
}
System.out.println("---------类成员变量如下-------------");
Field[] fie = test2.getDeclaredFields();
for (Field ff :fie){
int dd = ff.getModifiers();//变量修饰符
System.out.print(Modifier.toString(dd) + " ");
System.out.print(ff.getType().getName() + " ");//变量类型
System.out.println(ff.getName());//变量名
}
System.out.println("---------printParameter()方法调用-------------");
for(Method m:methods){
if(m.getName().equals("printParameter")){//调用方法名称为printParameter的方法
String re = (String)m.invoke(tt);//执行方法
System.out.println("方法返回:" + re);
}
}
}
}
class TestReflect {
static{
System.out.println("---------类加载中------------");
}
//成员变量
private int a;
private String b;
private float c;
public void init() {
this.a = 100;
this.b = "china";
this.c = 0.77f;
}
public void printParameter() {
init ();
System.out.println("a=" + a + " b=" + b + " c =" + c);
}
public String ex() {
this.b = "chinese";
System.out.println(b);
return this.b;
}
}
运行结果:
---------类加载中------------
---------类成员方法如下-------------
public void init(){}
public java.lang.String ex(){}
public void printParameter(){}
public final void wait(){}
public final void wait(long arg0, int arg1){}
public final native void wait(long arg0){}
public native int hashCode(){}
public final native java.lang.Class getClass(){}
public boolean equals(java.lang.Object arg0){}
public java.lang.String toString(){}
public final native void notify(){}
public final native void notifyAll(){}
---------类成员变量如下-------------
private int a
private java.lang.String b
private float c
---------printParameter()方法调用-------------
a=100 b=china c =0.77
方法返回:null
例2中可以看到,在程序运行中java可以根据类的名字获取类的所有信息同时还能调用类中的任意方法(当然,案例中我只写了片面,比如获取类实现的接口、抛出的异常等等都是可以的,这个自己去看api文档就可以了)——其实这个就是java的反射机制^_^
注:在类中方法、方法类型、成员变量类型、名称等都是一个对象