什么是反射呢?
我们都知道,java中,一个类有多个组成部分,例如:成员变量,方法,构造方法等。 反射就是加载类,并解剖出类的各个组成部分。
那么编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?
1. 当我们不知这个类的源码的时候,我们就需要把它解析出来。
2.框架中很多都运用到了反射。
<注意:Class类是Java反射的起源,针对任何一个你想勘探的类,只有先为它产生一个Class类的对象,接下来才能通过Class对象获取其它想要的信息。>
那么我们该如何使用反射呢?又该用其中的那些方法去加载和解剖出类的各个组曾部分呢?
Person类:
public class Person {
private String name;
public Person() {
}
public Person(String name){
this.name=name;
}
}
测试类:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.Test;
/**
* 反射测试
*
* @author LiZhuo
*
*/
public class Demo {
@Test
public void test() {
/**
* 怎么获取class对象
*/
// 第一种方式:
Person p = new Person();// 创建Person对象
Class c = p.getClass();// class对象操作(返回此Object的运行时类)
System.out.println("获取class对象为:" + c);
// 第二种方式:
try {
c = Class.forName("www.csdn.reflaction.Person");
System.out.println("获取class对象为:" + c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
// 第三种方式:
c = Person.class;
System.out.println("获取class对象为:" + c);
Integer i = 0;
System.out.println(i.getClass());
int a[] = { 1, 2 };
System.out.println(a.getClass());
}
@Test
public void constructor() throws Exception {
// 第一步:获取Class对象
Class c = Class.forName("www.csdn.reflaction.Person");
// 获取所有构造器
// 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法。
Constructor[] cs = c.getConstructors();// 返回constructor的数组
// 遍历(构造器)
for (Constructor<Person> p : cs) {
System.out.println(p.toString());
}
// 获取带有制定参数类型的构造器对象
Constructor<Person> pc = c.getConstructor(String.class);
System.out.println(pc.toString());
Constructor<Person> ps = c.getDeclaredConstructor(String.class);
System.out.println(ps.toString());
}
@Test
public void supClass() throws Exception {
// 第一步:获取Class对象
Class c = Class.forName("www.csdn.reflaction.Person");
// 获取父类对象
Class s = c.getSuperclass();
System.out.println(s.toString());
}
@Test
public void interfaces() throws Exception {
// 第一步:获取Class对象
Class c = Class.forName("java.util.ArrayList");
// 获取所有接口对象
Class cs[] = c.getInterfaces();// 返回一个数组
// 遍历数组
for (Class cx : cs) {
System.out.println(cx.toString());
}
}
@Test
public void methods() throws Exception{
// 第一步:获取Class对象
Class c = Class.forName("java.util.ArrayList");
//获取所有方法
Method meths[]=c.getMethods();
for(Method m:meths){
System.out.println(m.toString());
}
//获取制定方法
Method m=c.getMethod("remove",Object.class);
System.out.println("------"+m.toString());
}
@Test
public void fields() throws Exception{
// 第一步:获取Class对象
Class c = Class.forName("www.csdn.reflaction.Person");
Field f[]=c.getFields();
for(Field l:f){
System.out.println(l.toString());
}
}
@Test
public void field() throws Exception{
// 第一步:获取Class对象
Class c = Class.forName("www.csdn.reflaction.Person");
//Field f=c.getField("name");//私有属性不能直接访问
Field f=c.getDeclaredField("name");
System.out.println(f.toString());
}
}
因为我用的是JUnit来测试实现反射的,所以在这里并没有显式地显示每个测试方法的效果,大家可以自己试一试,根据每个方法看看每个方法对于类的剖析,以及输出的是什么。在这里我想告诉大家,因为运行中的类或接口在JVM中都会有一个对应的Class对象存在,它保存了对应类或接口的类型信息。要想获取类或接口的相应信息,需要先获取这个Class对象。 这也就是为什么需要在每个测试方法的第一条语句获取Class对象的原因了,希望大家能够注意,也希望能某些朋友得到一些启发。