当我们拿到一个类或者对象的时候就能够通过反射对它们进行操作,以下再来看反射:
为什么要用反射机制?直接创建对象不就能够了吗,这就涉及到了动态与静态的概念,静态编译:在编译时确定类型,绑定对象,即通过。动态编译:执行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用。用以减少类之间的藕合性。一句话,反射机制的长处就是能够实现动态创建对象和编译,体现出非常大的灵活性,特别是在J2EE的开发中 它的灵活性就表现的十分明显。比方,一个大型的软件,不可能一次就把把它设计的非常完美,当这个程序编译后,公布了,当发现须要更新某些功能时,我们不可能要用户把曾经的卸载,再又一次安装新的版本号,假如这种话。这个软件肯定是没有多少人用的。採用静态的话,须要把整个程序又一次编译一次才干够实现功能的更新,而採用反射机制的话,它就能够不用卸载,仅仅须要在执行时才动态的创建和编译,就能够实现该功能。
它的缺点是对性能有影响。使用反射基本上是一种解释操作。我们能够告诉JVM。我们希望做什么而且它满足我们的要求。这类操作总是慢于仅仅直接运行同样的操作。
<span style="font-size:18px;"><span style="font-size:14px;">/**
* 获取字节码Class对象的方法
* @throws ClassNotFoundException
*/
@Test
public void demo1() throws ClassNotFoundException{
//获取Class对象三种方式
//1.已知类
Class c1 = ReflectTest.class;
//2.已知对象
Object o = new ReflectTest();
Class c2 = o.getClass();
//3.未知类和对象,知道完整类名
String className = "com.lc.reflect.ReflectTest";
Class c3 = Class.forName(className);
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}</span></span><span style="font-size:18px;"><span style="font-size:14px;">/**
* 获取构造方法练习
* @throws Exception
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void demo2() throws Exception{
//获取的Person类字节码对象
String className = "com.lc.reflect.Person";
Class c = Class.forName(className);
//通过字节码对象获得全部的构造方法
Constructor[] constructors = c.getConstructors();
for (int i = 0; i < constructors.length; i++) {
System.out.println(constructors[i]);
}
//获取指定的构造方法
Constructor constructorDefault = c.getConstructor();
System.out.println(constructorDefault);
//Sring.class为String的字节码对象
Constructor constructor = c.getConstructor(String.class); //带參数类型为String的构造方法
System.out.println(constructor);
//创建对象实例的正常写法:
Person person1 = new Person();
Person person2 = new Person("lc");
//使用反射构造Person对象的实例
Person reflectPerson1 = (Person)constructorDefault.newInstance(); //无參构造方法
Person reflectPerson1_1 = (Person)c.newInstance(); //通过Class对象直接newInstance。将会默认调用目标类无參构造方法
Person reflectPerson2 = (Person)constructor.newInstance("lc");//參数为String类型的构造方法
}</span></span><span style="font-size:18px;"><span style="font-size:14px;">/**
* 使用反射操作类成员变量的练习
*/
@SuppressWarnings("rawtypes")
@Test
public void demo3() throws Exception{
//面向对象的写法是对象调用属性,而反射就正好相反了。。
Person p = new Person("lc");
System.out.println("对象调用属性的写法=====>:"+p.getName());
//使用反射操作类成员变量 --Field类
//1.必须获得目标类的字节码对象
Class c = Class.forName("com.lc.reflect.Person");
//2.操作成员实例变量name--获得name代表Field对象
Field[] f1 = c.getFields(); //获取全部public成员变量。包含父类继承
for (int i = 0; i < f1.length; i++) {
System.out.println(f1[i]);
}
Field[] f2 = c.getDeclaredFields(); //获取当前类定义的全部成员。包含private
for (int i = 0; i < f2.length; i++) {
System.out.println(f2[i]);
}
//获得name成员变量
Field field = c.getDeclaredField("name"); //当前field是private
//设置private变量能够訪问
field.setAccessible(true);
//获得p对象指定name属性值
Object value = field.get(p); //相当于p.getName();
System.out.println("反射操作成员变量的写法=====>"+value);
}
/**
* 使用反射改变成员变量的值(包含私有)
* @throws Exception
*/
@Test
public void demo4() throws Exception{
Person p = new Person();
//调用p对象中setName设置name的值
//1.获取字节码对象
Class c = Class.forName("com.lc.reflect.Person");
//2.操作setName获得setName对象反射对象的Method对象
//String类型參数setName方法
Method setName = c.getDeclaredMethod("setName", String.class);
//调用p对象中setName
setName.invoke(p, "sky"); //相当于p.setName("sky");
//3.读取name的值getName方法
Method getName = c.getDeclaredMethod("getName");
Object name = getName.invoke(p); //相当于p.getName();
System.out.println("反射获取成员变量的值======>"+name);
}</span></span><span style="font-size:18px;"><span style="font-size:14px;">/**
* 操作方法对象
* @throws Exception
*/
@Test
public void demo5() throws Exception{
//已知String类型完整类名---获得字节码对象
String className = "com.lc.reflect.Person";
Class c = Class.forName(className);
//已知Class对象。构造实例
Object obj = c.newInstance(); //调用无參构造方法
//获得字节码对象中指定属性和方法
//获得name属性
Field f = c.getDeclaredField("name");
//获得setName方法
Method setName = c.getDeclaredMethod("setName", String.class);
//改动属性的值,运行对应方法
f.setAccessible(true);
f.set(obj, "sky");
setName.invoke(obj, "sky_lc");
//以上代码等价于以下的代码
Person p = new Person();
//p.name = "sky";
p.setName("sky_lc");
}</span></span>
仅反射在性能关键的应用的核心逻辑中使用时性能问题才变得至关重要。
所以。合理的使用反射将大大提高我们程序的通用性和复用性。
原文:http://www.cnblogs.com/jzdwajue/p/6797716.html