一个类 有组多个组成部分,例如成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。反射常常用于框架。
加载类
如图的操作便可以进行类的加载,通过如下的常用方法可以解剖类:
这些方法可以解剖出构造函数,方法和成员变量(属性)。前三种解剖调出的是声明为public的内容,如声明为private的组成部分,需要使用后三种方法。
解剖出这些成员的作用:
构造函数:创建对象,完成数据初始化,可以利用解剖出的构造函数进行创建对象;字段:封装数据,解剖出可以用于封装数据;成员方法:解剖出之后可以使用。
通过反射的构造函数创建对象:
package cn.itcast.reflrct;
import java.util.List;
public class Person {
String name = "aaa";
public Person(){
System.out.println("person");
}
public Person(String name){
System.out.println("person name password");
}
private Person(List list){
System.out.println(list);
}
public void aa1(){
System.out.println("aa1");
}
public void aa1(String name,int password){
System.out.println(name + ":" + password);
}
}
package cn.itcast.reflrct;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
//反射类的构造函数,创建类对象
public class demo2 {
//反射构造函数
@Test
public void test1() throws Exception {
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Constructor c = clazz.getConstructor(null);
Person p =(Person)c.newInstance(null);//newInstance返回的是Object,需要进行类型转换
System.out.println(p.name);
}
@Test
public void test2() throws Exception{
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Constructor c= clazz.getConstructor(String.class);//表示是String类型参数的构造函数
Person p = (Person)c.newInstance("xxxx");
System.out.println(p.name);
}
@Test
public void test3() throws Exception{
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Constructor c= clazz.getConstructor(List.class);//表示是可变参数类型参数的构造函数
c.setAccessible(true);//暴力反射,正常私有成员不许外界反射
Person p = (Person)c.newInstance(new ArrayList());
System.out.println(p.name);
}
//创建对象的另一种方法
@Test
public void test4() throws Exception{
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Person p = (Person) clazz.newInstance();//要求Person类必须要有无参的构造函数
//无参的情况下等效于test1()
System.out.println(p.name);
}
//反射类方法
@Test
public void test5() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Method method = clazz.getMethod("aa1",String.class,int.class);//对于private方法使用getDeclaredMethod()
method.invoke(p, "asd",38);//如果为static方法,可以不需要对象
}
//反射main方法
@Test
public void test5() throws Exception{
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Method method = clazz.getMethod("main",String[].class);
method.invoke(null,new Object[](new String[]("aaa","bbb"));//此处为通过反射调用参数为数组的方法,需要注意,为static方法,可以不需要对象,所以为null
}
//反射字段
@Test
public void test6() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflrct.Person");
Field f = clazz.getField("name");//获取字段name,getField内填写字段名称
Class type = f.getType();//获取字段类型
if(type.equals(String.class)){
String name = (String) f.get(p);
System.out.println(name);
}
//设置字段值
f.set(p, "sssss");
System.out.println(p.name);
}
}
使用Junit进行单元测试,此处用反射类方法举例: