在看张老师的视屏之前,每每遇到反射,我只想说“它妈的:Q”,但是现在我会说“亲爱的:D”
反射的基石—>Class类
把一些具有相同属性和行为的对象抽象出来成为一个类,类与对象的关系是抽象与具体,共性与个性的关系,类是描述抽象的概念,对象是类的一个具体实例。
查看JDK-API文档
Class 类的实例表示正在运行的 Java 应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也表示为 Class 对象。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
每一个类在内存中都是一段字节码,每一段字节码是一个具体的对象,是某一个类型
Constructor代表类的构造方法
反射到底是什么东西?
反射就是把java类中的各成分映射成相应的java类……………………………………………...冯伟立
Constructor类代表某个类中的一个构造方法
可以得到某个类的所有构造方法:
Constructor[] constructors = Class.forName(“java.lang.String”).getConstructors();
可以得到某一个构造方法:
Constructor constructor = Class.forName(“java.lang.String”).getConstructor(StringBuffer.class);
//获得方法时要用到类型
可以创建一个实例对象:
通常方式:String str = new String(new StringBuffer(“abc”));
反射方式:String str = (String)constructor.newInstance(new StringBuffer(“abc”));
//调用获得时的方法时要用到上面相同类型的实例
Class.newInstance()方法:
例子:String obj = (String)Class.forName(“java.lang.String”).newInstance();
该方法内部先得到默认的构造方法,让后用该构造方法创建实例对象。
该方法内部的具体代码到底是什么样的呢?用到了缓存机制来保存默认构造方法的实例对象。
Field类代表某一个类中的一个成员变量(一个字段)
用eclipse自动生成Java类的构造方法
字段的反射:
public class ReflectPoint {
private int x;
public int y;
public ReflectPoint(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
import java.lang.*;
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws Exception {
ReflectPoint pt1 = new ReflectPoint(2, 3);
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));
Field fieldX = pt1.getClass().getDeclaredField("x");
//暴力方式设置私有变量x为可读取的!
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
}
}
问题来了:得到的Field对象fieldX与fieldY是对应到类上面的成员变量,还是对应到对象上的成员变量?类只有一个,对象可以有多个,假设与对象关联(即得到的Field对象是fieldX与fieldY是类的某一个具体实例),那么关联的是哪个对象呢?所以字段fieldX代表的是ReflectPoint类中的x的定义,而不是某一对象具体的值。
练习:将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”b”改成”a”。
public static void changeStringValue(Object obj) throws Exception{
Field[] fields = obj.getClass().getFields();
for(Field field:fields){
if(field.getType() == String.class){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b', 'a');
field.set(obj, newValue);
}
}
}
Method类代表类里面的一个成员方法(字节码里面的方法,而不是一个对象身上的方法)
得到类中的某一个方法:
Method charAt = Class.forName(“java.lang.String”).getMethod(“charAt”,int.class);
用反射来得到一个方法,从String这个字节码身上拿来的
已知String str = “abc”,下面用反射来实现str.charAt(1);
Method methodCharAt = String.class.getMethod(String name,Class<?>…parameterTypes)
//invoke(Object obj,Object…args)对带有指定参数(1)的指定对象(str)调用由此 Method 对//象表示的底层方法
System.out.println(methodCharAt.invoke(str,1));
如果传递给Method对象的invoke方法的第一个参数为null,这又有什么意义呢?这说明了该Method对象对应的是一个静态方法(这句怎么理解? 静态方法调用时不需要对象!)
得到输出结果是:b
专家模式:谁拥有这个数据,谁就能干这件事(比如:人关门这件事,关门这个动作只属于门的,人只是负责发出关的命令;再比如:火车司机刹车,司机不可能把火车停下来对吧!司机只是发出信号,刹车动作本身是属于火车的)
|