------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、反射概述
概述
Java的反射机制是在运行状态中,对于任意的一个类,都能知道这个类的所有属性和方法;
对于任意一个对象,都能调用他的任意一个方法和属性;
这种动态获取的信息以及动态调用对象的方法称为Java语言的反射机制。
动态获取类中信息,就是java反射。可以理解为对类的解剖。
什么时候用反射技术
如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了反射技术。
反射的好处
大大的增加了程序的扩展性
反射的基本步骤
获得Class对象,就是获取到指定的名字的字节码文件对象
实例化对象,获得类属性,方法或构造函数
访问属性,调用方法,调用构造函数创建对象
字节码文件对象的三种获取方式
1、getClass方法
如果拿到了对象,不知道是什么类型,用于获得对象的类型
Class clazz = new Refletc().getClass;//弊端:必须要创建该类对象才能调用getClass方法
2、类名.class
如果是明确地获得某个类的Class对象 主要用于传参
Class.clazz = Reflect.class;//弊端:这种方式还要明确类
以上两种方法都不利于程序的扩展
3、Class.forname(类名);//优点:有名称就可以,便于程序扩展
指定什么类名,就获取什么类字节码文件对象
三种代码示例
String str1 = "abc";
Class cls1 = str1.getClass();
Class cls2 = String.class;
Class cls3 = Class.forName("java.lang.String");
二、反射的构造方法
1、getConstructor(Class cls);//得到一个构造方法
2、newInstance();//产生一个空参数,并且将其初始化
使用反射的方式实现new String(new StringBuffer("abc"));代码
class {
public static void main(String[] args) {
String.class.getConstructor(StringBuffer.class,int.class);//获取接收两个参数的构造方法
//使用反射的方式实现new String(new StringBuffer("abc"));
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);//String.class的字节码是constructor1
String str = (String)constructor1.newInstance(new StringBuffer("abc"));//创建实例化对象
//第一个StringBuffer表示选择使用哪个参数的构造方法,第二个用这个构造方法时还得传StringBuffer的对象进去
System.out.println(str.charAt(2));
}
}
三、成员变量的反射
方法
getField("变量名");//获取一个类中的公有成员变量,私有的获取不到。返回一个Field类对象。
setAccessible(true);//参数为true,可以针对私有成员进行暴力访问,称为暴力反射。
getDeclaredField("变量名");//可以获取到私有和公有的成员变量。
set(Object obj,value);//设置value到对象中,相当于给成员变量赋值
练习:需求将任意一个对象中的所有String类型的成员变量所对应字符串内容中的“b”改成“a”
class {
public static void main(String[] args) {
ReflectDemo pt1 = new ReflectDemo(3,5);
changeStringValue(pt1);
System.out.println(pt1);
}
private static void changeStringValue(Object obj) throws Exception {
Field[] fields = obj.getClass().getFields();//obj.getClass()返回类的字节码
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);
}
}
}
}
public class ReflectDemo {
private int x;
public int y;
public String str1 = "ball";
public String str2 = "basketball";
public String str3 = "iasdf";
public ReflectDemo(int x, int y) {
super();
this.x = x;
this.y = y;
}
public String toString(){
return str1+":"+str2+":"+str3;
}
}
四、成员函数的反射
获取类中所有的方法
</pre><pre name="code" class="java">public static void method_1() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
Method[] methods = clazz.getMethods();//获取的是该类中的公有方法和父类中的公有方法。
methods = clazz.getDeclaredMethods();//获取本类中的方法,包含私有方法。
for(Method method : methods) {
System.out.println(method);
}
}
获取指定的方法
public static void method_2() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
//获取指定名称的方法。
Method method = clazz.getMethod("show", int.class,String.class);
//想要运行指定方法,当然是方法对象最清楚,为了让方法运行,调用方法对象的invoke方法即可,但是方法运行必须要明确所属的对象和具体的实际参数。
Object obj = clazz.newInstance();
method.invoke(obj, 39,"hehehe");//执行一个方法
}
public static void method_3() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
//想要获取私有方法。必须用getDeclearMethod();
Method method = clazz.getDeclaredMethod("method", null);
// 私有方法不能直接访问,因为权限不够。非要访问,可以通过暴力的方式。
method.setAccessible(true);//一般很少用,因为私有就是隐藏起来,所以尽量不要访问。
}
反射静态方法
public static void method_4() throws Exception {
Class clazz = Class.forName("cn.itcast.bean.Person");
Method method = clazz.getMethod("function",null);
method.invoke(null,null);
}
五、反射的应用
反射的作用
反射的作用是实现框架功能
框架和工具类有区别:工具类是被用户的类调用,而框架则是调用用户提供的类
因为在写程序时无法知道要被调用的类名,所以在程序中无法直接new某个类的实例对象,而要用反射方式做