反射部分一直欠着,现在学框架和Servlet必须要学一下了。最近学习Struts2框架和Servlet时候,很多地方直接给出类名就可以去使用了,如在web.xml
中配置Filter时:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>myFilter.Filter1</filter-class>
<init-param>
<param-name>who</param-name>
<param-value>汪汪汪汪</param-value>
</init-param>
</filter>
直接给出了包名.类名,却可以使用它。又如在Sturts2框架struts.xml
中配置Action时:
<action name="main" class="myAction.MainAction">
<result name="error">/login2.jsp</result>
</action>
直接给出了实现类的位置,在代码中并没有new 构造器()
一个这个类的对象,却能使用它的对象。这些部分都使用到了反射。
简述反射
反射机制就是通过RTTI(运行时类型识别),在Java程序运行时能够对任意一个类构造对象、获取和使用成员变量和方法,对任意一个对象判断所属的类、使用成员方法。因为是任意一个,意味着反射可以越过权限检查,并且会破坏封装性。
实际上的做法是将这个类中的各类信息映射成了对象,所以才能直接使用。
Class对象及其获取
Class对象是Java类编译成class文件时生成在class文件内的,它是java.lang.Class
的实例,用来保存Java类本身的类型信息。
获取Class对象可以用Objet类的getClass()
成员方法,可以用数据类型的class
属性直接获取,也可以用Class.forName("类名")
获取:
package testReflect;
//自定的一个类
class MyClass {
}
// 在主类main方法中测试
public class Main {
public static void main(String[] args) {
// 对象调用getClass()获取
Class cls1 = new MyClass().getClass();
System.out.println(cls1);
// 获取class成员
Class cls2 = MyClass.class;
System.out.println(cls2);
// 对基本数据类型也可以
Class cls_dbl = double.class;
System.out.println(cls_dbl);
// Class.forName()加载
try {
Class cls3 = Class.forName("testReflect.MyClass");
System.out.println(cls3);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输出:
class testReflect.MyClass
class testReflect.MyClass
double
class testReflect.MyClass
反射主要是在用第三种方法,在没有导入类时根据位置加载Class对象。
获取类的成员变量
package testReflect;
import java.lang.reflect.Field;
import java.util.Date;
//自定的一个类
class MyClass {
private int int_prvt;// 私有int
public double dbl_pblc;// 公有double
private Date dt_prvt;// 私有Date
public MyClass mc_pblc;// 公有MyClass
}
// 在主类main方法中测试
public class Main {
public static void main(String[] args) {
try {
// 加载Class对象
Class cls = Class.forName("testReflect.MyClass");
System.out.println("加载了:" + cls.getName() + "类");
// 获取所有的public属性
Field[] ary_fd1 = cls.getFields();
System.out.print("所有的public属性:");
for (Field f : ary_fd1) {
System.out.print(f.getName() + " ");
}
System.out.println();
// 获取所有的属性
Field[] ary_fd2 = cls.getDeclaredFields();
System.out.print("所有的属性:");
for (Field f : ary_fd2) {
System.out.print(f.getName() + " ");
}
System.out.println();
// 获取指定的public属性
Field fd3 = cls.getField("mc_pblc");
System.out.println("指定的public属性:" + fd3.getName());
// 获取指定的属性
Field fd4 = cls.getDeclaredField("dt_prvt");
System.out.println("指定的属性:" + fd4.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
输出:
加载了:testReflect.MyClass类
所有的public属性:dbl_pblc mc_pblc
所有的属性:int_prvt dbl_pblc dt_prvt mc_pblc
指定的public属性:mc_pblc
指定的属性:dt_prvt
获取类的成员方法
package testReflect;
import java.lang.reflect.Method;
import java.util.Date;
//自定的一个类
class MyClass {
private int int_prvt() {
return 0;
};
public double dbl_pblc() {
return 0.0;
};
private Date dt_prvt() {
return null;
};
public MyClass mc_pblc() {
return this;
};
}
// 在主类main方法中测试
public class Main {
public static void main(String[] args) {
try {
// 加载Class对象
Class cls = Class.forName("testReflect.MyClass");
System.out.println("加载了:" + cls.getName() + "类");
// 获取所有的public方法
Method[] ary_mthd1 = cls.getMethods();
System.out.print("所有的public方法(包括父类的):");
for (Method m : ary_mthd1) {
System.out.print(m.getName() + " ");
}
System.out.println();
// 获取所有的方法
Method[] ary_mthd2 = cls.getDeclaredMethods();
System.out.print("所有的方法:");
for (Method m : ary_mthd2) {
System.out.print(m.getName() + " ");
}
System.out.println();
// 获取指定的public方法
Method mthd3 = cls.getMethod("mc_pblc");
System.out.println("指定的public方法:" + mthd3.getName());
// 获取指定的方法
Method mthd4 = cls.getDeclaredMethod("dt_prvt");
System.out.println("指定的方法:" + mthd4.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
输出:
加载了:testReflect.MyClass类
所有的public方法(包括父类的):mc_pblc dbl_pblc wait wait wait equals toString hashCode getClass notify notifyAll
所有的方法:mc_pblc dt_prvt int_prvt dbl_pblc
指定的public方法:mc_pblc
指定的方法:dt_prvt