前段时间看到自己写的JDBC ,瞄了一眼class.forName字段,突然想起哪里好像说过这是用到了反射机制,顺便就接触了解了下反射,写下这篇总结,供自己以后参考。
简单的说,反射其实是指程序在运行时 能够获得自身的信息,在JAVA中,我们只要知道这个类的名字,就可以同过这个反射机制来获得该类的各个信息。
反射算是一种动态代理,能够实现动态创建对象和编译。
那么反射需要用到class类,即java.lang.class这个类,当一个类被加载后,jvm会给我们自动生成一个class对象。同时关于反射,java附带的库java.lang.reflect包含了:
Field,Method,Constructor类。
关于获得Class类的对象 贴出我写的代码
package guohao;
import java.lang.reflect.Method;
public class Cynbl {
private String name ;
public int age ;
@Override
public String toString() {
return "Cynbl [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//无参构造
public Cynbl() {
System.out.println("无参构造");
}
private Cynbl(int age) {
this.age = age;
System.out.println("1参构造");
}
private Cynbl(int age,String name) {
this.age = age;
this.name = name;
System.out.println("2参构造");
}
public void show(){
System.out.println("反射开始");
}
public void showname(String name){
System.out.println("我的名字是"+name);
}
public void showage(int age){
System.out.println("我的年龄是"+age);
}
}
这是一个Cybnl类,其中我定义了name和age两个变量,权限不同,并有各种有参无参的构造器以及各成员方法,下面,我通过各种方法来获得该类的信息:
package guohao;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import org.junit.Test;
public class Fanshe {
//没有反射
@Test
public void noReflection(){
Cynbl c = new Cynbl();
c.setAge(20);
c.setName("单身狗");
System.out.println(c);
c.show();
c.showname("杰宝");
}
//有了反射
@Test
public void haveReflection() throws Exception{
//方法一
Class<Cynbl> clazz = (Class<Cynbl>) Class.forName("guohao.Cynbl");
//方法二
//Class<Cynbl> clazz1 = Cynbl.class;
//一
//Cynbl cynbl = clazz.newInstance();
//方法二获取无参构造方法,参数为空,因为无参构造方法没有参数
Constructor cst = clazz.getConstructor();
Object obj = cst.newInstance();
System.out.println(obj);
//System.out.println(cynbl);
//Field f1 = clazz.getField("age");
//f1.set(cynbl, 20);
//私有变量
//Field f2 = clazz.getDeclaredField("name");
//f2.setAccessible(true);
//f2.set(cynbl, "单身狗");
//cynbl.show();
//System.out.println(cynbl);
//System.out.println(clazz);
//System.out.println(clazz1);
}
}
其中clazz和clazz1为同一个对象,所有的类都是Class的对象,在这里,获得构造器的方法(Constructor)以及获得类的方法(Method)我没有详细写出,在不同的修饰符下,方法不同,如是私有的则需要我所理解的暴力破解(xx.getDeclaredxx;xx.SetAccessible(true));
反射暂时学到这里,其实我们平时可以运用反射机制+配置文件达到轻松解决不停改变调用的方法的问题,只需要修改配置文件即可。