黑马程序员—高新技术: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:通过反射获取构造方法并使用
B:通过反射获取成员变量并使用
C:通过反射获取成员方法并使用
----------------------
ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net
一 反射的基石,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
相关文章推荐
- 黑马程序员 IO流 一
- 黑马程序员—多线程
- 黑马程序员—抽象类和接口
- 黑马程序员——正则表达式
- 黑马程序员---JAVA基础--正则表达式(十六)
- 每天工作四小时的程序员-转
- 告别码农,成为真正的程序员
- 黑马程序员 集合框架
- 黑马程序员 字符串
- 黑马程序员 线程同步
- 黑马程序员 包
- 黑马程序员 基础篇(四)
- 黑马程序员 基础篇(三)
- loading黑马程序员之IO字节流(2-2)
- 黑马程序员—这是一个能够键盘录入路径去批量修改指定文件夹下所有指定文件内容的方法
- 分享8年开发经验,浅谈程序员职业规划
- JAVA面试精选【Java算法与编程二】
- 黑马程序员——反射问题代码学习点
- 黑马程序员_ADO.NET学习
- 程序员练级之路