您的位置:首页 > 职场人生

黑马程序员—高新技术:Reflect反射

2013-12-29 22:53 218 查看
<---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------/p>
一 反射的基石,class类。

Java程序中各个Java类属于同一类事物,描述这一类事物的Java类名就是Class。
例如我们将人定义为person类,将动物定义为Anime类,而众多诸如此类该如何通过Java描述呢,我们称其为class类。
这个特性自Java1.2开始出现,非常强大。将来我们所用的很多框架,都要用到反射技术。
一般我们在定义一个类的时候,class这个单词是小写的。而当我们对类进行描述的时候,类类型Class要采取大写。
class:Java中的类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由此类的实例对象确定,不同的实例对象有不同的属性值。
Class:指的是Java程序中的各个Java类是属于同一类事物,都是Java程序的类,这些类称为Class。例如人对应的是Person类,Java类对应的就是Class。
        一个Java类有它的各种属性和方法,有它的父类等等。而通过Class,我们可以得到它方方面面的信息。这个类似逆推的过程就叫做反射。
Class类中的常用方法:
getName()        获取类的名字。
getPakage()        得到自己所属的包。
getMethod()        得到自己所有的方法。
getInterface()      得到自己实现的多个接口。
等等这些方法,我们可以通过它们得到所需的信息。
反射是什么?
反射是个动词,就是通过字节码文件对象,来使用构造方法,成员变量,成员方法。这个过程叫做反射。
反射的一切都是建立在Class字节码文件之上,首先要考虑的是该如何得到一份字节码文件。
获取字节码文件对象有三种方式:
A:使用Object类的getClass()方法
B:使用数据类型.class静态属性
C:使用Class类的forName()静态方法
推荐使用:第三种,因为第三种可以结合配置文件使用。
/*
*
* 你想使用这些内容,那么首先要做的事情,就是你能够获取到字节码文件对象。
* 如何获取Class的对象呢?
* A:使用Object类的getClass()方法。
* B:使用数据类型.class这个静态的成员变量。
* C:使用的是Class类的forName()静态方法。
* public static Class<?> forName(String className)
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
// 方式1
Person p = new Person();
Person p2 = new Person();

Class c = p.getClass();
Class c2 = p2.getClass();

System.out.println(p == p2);// false
System.out.println(c == c2);// true

// 方式2
Class c3 = Person.class;
System.out.println(c == c3);

// 方式3
// public static Class<?> forName(String className)
Class c4 = Class.forName("cn.itcast_01.Person");
// cn.itcast_01.Person
// cn.itcast_01.Person
System.out.println(c == c4);
}
}
class Person {
private String name;
public int age;

public Person() {
}

Person(String name) {
this.name = name;
}

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public void show() {
System.out.println("show");
}

public void method(String name) {
System.out.println("method " + name);
}

public String function() {
return "hello";
}

public String sum(int a, String b) {
return String.valueOf(a).concat(b);
}

private void print() {
System.out.println("print");
}

public String toString() {
return "name:" + name + ",age:" + age;
}
}

以上的代码实现了获取Class字节码文件的三种方式。反射纠结能做哪些比较具体的应用呢?

简单说有三种:

A:通过反射获取构造方法并使用

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/*
* 通过反射获取带参构造器并创建对象。
*/
public class ReflectDemo2 {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
// 获取字节码文件对象
Class c = Class.forName("Person");

// 获取带参构造器对象
Constructor con = c.getConstructor(String.class, int.class);
// Person(String name,int age);

// 创建对象
// public T newInstance(Object... initargs)
Object obj = con.newInstance("奶茶", 22);
System.out.println(obj);
}
}


B:通过反射获取成员变量并使用

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/*
* 通过反射获取成员变量对象并使用。
*
* 需求:
* Person p = new Person();
* p.name = "奶茶";
* p.age = 22;
*/
public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException,
NoSuchMethodException, SecurityException, InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchFieldException {
// 获取字节码文件对象
Class c = Class.forName("Person");

// 创建一个对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();

// 获取单个成员变量对象
Field field = c.getField("age");

//给obj对象的指定的字段赋值为指定的值
field.set(obj, 20);//给obj对象的field字段赋值为20
System.out.println(obj);

}
}


C:通过反射获取成员方法并使用

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

/*
* 通过反射获取成员方法对象并使用。
*/
public class ReflectDemo {
public static void main(String[] args) throws Exception {
// 获取字节码文件对象
Class c = Class.forName("Person");

// 通过无参构造创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();

// 单个方法的获取

// 无参,无返回值;
Method m = c.getMethod("show");
m.invoke(obj);
System.out.println("*********");

// 带参,无返回值
Method m2 = c.getMethod("method", String.class);
m2.invoke(obj, "hello");
System.out.println("*********");

// 无参,有返回值
Method m3 = c.getMethod("function");
Object m3Obj = m3.invoke(obj);
System.out.println(m3Obj);
System.out.println("*********");

// 带多个参数,有返回值
Method m4 = c.getMethod("sum", int.class, String.class);
Object m4Obj = m4.invoke(obj, 100, "abc");
System.out.println(m4Obj);
System.out.println("*********");

//私有方法的使用
Method m5 = c.getDeclaredMethod("print");
m5.setAccessible(true);
m5.invoke(obj);
}
}
案例:改变任意对象中所有STRING类型成员变量所对应的字符串内容;
import java.lang.reflect.Field;

//题目:将任意一个对象中的所有string类型的成员变量所对应的字符串内容的“b”改成“a”.
/*
* 思路要对对象进行扫描,得到它所有的成员变量,也就是字段。再做修改
* 	步骤1,写一个方法,传入对象。
* 	2,通过对象,可以反射得到他的所有字段,并 传入数组
* 	3,迭代每一个字段,然后再得出每个字段的类型。(这个时候类型并不明确),如何确认类型呢?则通过比较完成。
* 然后对获得的每一个字段进行修改。注意,在判断迭代条件的时候,由于同属一个字节码,==号的语义比equals来的准确。
* */
public class ReflectTest {
/**
* @param args
*/
public static void main(String[] args)throws Exception {
//先得有个类的实例对象
ReflectExample re =new ReflectExample();
changeStringValue(re);
System.out.println(re);
}

private static void changeStringValue(Object obj) throws Exception{//方法
//获得所有字段
Field[] fields =obj.getClass().getFields();
//这里要注意,获得指定字段的方法是getField(指定名称); 获得所有字段的方法是getFields();
for (Field field : fields) {
//getType()能获得字段的类型。
if(field.getType()==(String.class)){
//这里先要获得具体的值再作修改;返回值是String类型。经过判断,知道这里得出的也是String类型。
String oldValue=(String)field.get(obj);
//得到具体的字段值之后呢,可以对值进行改变。
String newValue=oldValue.replace("b", "a");
//这里输入换完了值,但是对象本身的值没有被改变。目前只是将值取出而已。只get还没有set.下面的方法是对对象的值进行设置。
field.set(obj, newValue);
//为了得到我们的结果,还要重写toString方法。
}
}
}

}
class ReflectExample {
public String str1 ="ball";
public String str2 ="baskeball";
public String str3 ="itcast";
@Override
public String toString() {
return str1+"***"+str2+"***"+str3+"***";
}

}


----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: