一个类是有多个部分组成的,如构造函数.字段.属性.方法等;
反射就是加载类,并解剖出类的各个组成部分.
编程是什么情况下才需要加载类,并解剖出类的各个组成部分呢?
一般框架是基于配置文件的,首先,配置文件需要获得当前类,然后再解剖类中的方法.
反射是java中很重要的一门技术,如果这部分学不明白,那么以后框架就很难学明白了.
加载类通过Class.forName(类的完整限定名);按F2可获得此类的完整限定名.
//反射:加载类,获得Class
方式一:
Class cla1= Class.forName("gw.reflect.Person");
方式二:
Class cla2 = new Person().getClass();
方式三:
Class cla3 = Person.class;
System.out.println(cla1);
Class对象提供了如下常用的方法
Constructor<T> | getConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。 |
Method | getMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 |
Field[] | getFields() 返回一个包含某些 Field 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有可访问公共字段。 |
以上方法仅限于获得类中的public修饰的成员,对于其他修饰的则无法获得.
想要获得的话,需要使用如下方法才可.
Constructor<T> | getDeclaredConstructor(Class<?>... parameterTypes) 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。 |
|
|
Method | getDeclaredMethod(String name,Class<?>... parameterTypes) 返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 |
@Test
// public Person()
public void test1() throws Exception {
// 加载类
Class clazz = Class.forName("gw.reflect.Person");
// 获得无参的构造函数,无参用null表示
Constructor con = clazz.getConstructor(null);
// 有了构造函数就可以实例化该类的一个对象
Person p = (Person) con.newInstance(null);
System.out.println(p.name);
}
@Test
// public Person(String name)
public void test2() throws Exception {
Class clazz = Class.forName("gw.reflect.Person");
// java中都是用类表示的
Constructor con = clazz.getConstructor(String.class);
Person p = (Person) con.newInstance("gg");
System.out.println(p.name);
}
@Test
// public Person(String name,int age)
public void test3() throws Exception {
Class clazz = Class.forName("gw.reflect.Person");
Constructor con = clazz.getConstructor(String.class, int.class);
Person p = (Person) con.newInstance("ff", 12);
System.out.println(p.name);
}
@Test
// private Person(List list)
public void test4() throws Exception {
Class clazz = Class.forName("gw.reflect.Person");
// 获得类中的私有构造函数
Constructor con = clazz.getDeclaredConstructor(List.class);
con.setAccessible(true);// 私有构造函数的获得需要先暴力反射
Person p = (Person) con.newInstance(new ArrayList());
System.out.println(p.name);
}
@Test
// public Person()
public void test5() throws Exception {
Class clazz = Class.forName("gw.reflect.Person");
// sun公司提供的通过class实例化类的对象的一个方法
Person p = (Person) clazz.newInstance();
p.eat();
}
获得方法
@Test
// public void aa1()
public void test1() throws Exception {
Person p = new Person();
// 加载类
Class clazz = Class.forName("gw.reflect.Person");
// 获得方法getMethod(方法名,参数列表)
Method me = clazz.getMethod("aa1", null);
// 方法的调用invoke(对象,参数)
me.invoke(p, null);
}
@Test
// public void aa1(String name, int age)
public void test2() throws Exception {
// 对象
Person p = new Person();
// 加载类
Class clazz = Class.forName("gw.reflect.Person");
// 获得方法getMethod(方法名,类)
Method me = clazz.getMethod("aa1", int.class);
// 调用方法
me.invoke(p, 13);
}
@Test
// public Class[] aa1(String name,int[] age)
public void test3() throws Exception {
Person p = new Person();
// 加载类
Class clazz = Class.forName("gw.reflect.Person");
// 获得方法
Method me = clazz.getMethod("aa1", String.class, int[].class);
//
Class[] cs = (Class[]) me.invoke(p, "gg", new int[] { 1, 2, 3 });
System.out.println(cs[0]);
}
@Test
// public void aa1(InputStream in)
public void test4() throws Exception {
Person p=new Person();
Class clazz = Class.forName("gw.reflect.Person");
Method me = clazz.getMethod("aa1", InputStream.class);
me.invoke(p,new FileInputStream("w:\\1.txt"));
}
@Test
// public static void aa1(int num)
public void test5() throws Exception {
// 加载类
Class clazz = Class.forName("gw.reflect.Person");
// 获得方法getMethod(方法名,类)
Method me = clazz.getMethod("aa1", int.class);
// 调用方法invoke(对象,参数值)
me.invoke(null, 12);
}
主方法
@Test
//public static void main(String[] args)
public void test() throws Exception{
Person p = new Person();
Class clazz = Class.forName("gw.reflect.Person");
Method me=clazz.getMethod("main", String[].class);
//反射调用一个接收数组的方法时,为了保证向下兼容性,它会先拆数组
//方式一:new Object[]{参数}
//方式二:Object(参数)
me.invoke(p,new Object[]{ new String[]{"aa","bb"}});
}
获取字段
@Test
// public String name = "gw";
public void test1() throws Exception {
Person p = new Person();
Class clazz = Class.forName("gw.reflect.Person");
Field f = clazz.getField("name");
// 获取字段的值
String value = (String) f.get(p);
// 获取字段的类型
Class type = f.getType();
if (type.equals(String.class)) {
String fv = (String) value;
System.out.println(fv);
}
@Test //private int age = 15;
public void test2() throws Exception {
Person p= new Person();
Class clazz = Class.forName("gw.reflect.Person");
//获取public之外修饰符修饰的字段
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);//暴力访问
int a=(Integer)f.get(p);
System.out.println(a);
f.set(p, 11);
System.out.println(f.get(p));
}
@Test
//public static int sex = 0;
public void test3() throws Exception{
Person p = new Person();
Class clazz = Class.forName("gw.reflect.Person");
Field f = clazz.getField("sex");
System.out.println(f.get(p));
//f.set(null, 1);
f.set(p,1);
//获取字段的值
System.out.println(f.get(p));
}
参考: Person.class
public class Person {
public String name = "gw";
private int age = 15;
public static int sex = 0;
public Person() {
System.out.println("无参构造函数...");
}
public Person(String name) {
System.out.println("一餐构造函数");
}
public Person(String name, int age) {
System.out.println("俩参构造函数");
}
private Person(List list) {
System.out.println("private list构造函数");
}
public void aa1() {
System.out.println("aa1");
}
public void aa1(String name, int age) {
System.out.println(name + ":" + age);
}
public Class[] aa1(String name,int[] age){
return new Class[]{String.class};
}
public void aa1(InputStream in){
System.out.println(in);
}
public static void aa1(int num){
System.out.println(num);
}
public static void main(String[] args){
System.out.println("main...");
}
}