java 反射机制
反射的功能
API简介
方法介绍
获取Class的三种方式
生成对象
反射访问私有(private)的方法
反射机制的优点与缺点
JAVA反射机制是在运行状态中,动态获取的类的所有信息以及动态调用对象的方法(或属性),称为java语言的反射机制。
反射的功能
Java反射机制主要提供了以下功能:
- 在运行时判断任意一个对象所属的类;
- 在运行时构造任意一个类的对象;
- 在运行时判断任意一个类所具有的成员变量和方法;
- 在运行时调用任意一个对象的方法;生成动态代理。
API简介
在这里先看一下sun为我们提供了那些反射机制中的类:
— java.lang.Class; 代表一个类
— java.lang.reflect.Constructor; 代表类的构造方法
— java.lang.reflect.Field; 代表类的成员变量(成员变量也称为类的属性)
— java.lang.reflect.Method; 代表类的方法
— java.lang.reflect.Array; 提供了动态创建数组,以及访问数组的元素的静态方法
注意:java中无论生成某个类的多少对象, 这些对象都会对应于同一个Class对象。
方法介绍
方法关键字 | 含义 |
getDeclaredMethods() | 获取所有的方法 |
getReturnType() | 获得方法的放回类型 |
getParameterTypes() | 获得方法的传入参数类型 |
getDeclaredMethod("方法名",参数类型.class,……) | 获得特定的方法 |
构造方法关键字 | 含义 |
getDeclaredConstructors() | 获取所有的构造方法 |
getDeclaredConstructor(参数类型.class,……) | 获取特定的构造方法 |
父类和父接口 | 含义 |
getSuperclass() | 获取某类的父类 |
getInterfaces() | 获取某类实现的接口 |
获取Class的三种方式
1)使用Class类的forName(String className)静态方法。改方法需要传入字符串参数,改字符串参数的值是某个类的全限定类名(必须添加完整的包名)。
Class.forName("java.lang.String");
2)调用某个类的class属性来获取该类对应的class对象,如
String.class
3)调用某个对象的getClass方法。
String s = "aa"; Class<?> clazz = s.getClass();
生成对象
1)通过不带参数的构造方法生成对象有两种方法
a)先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可:
newInstance()方法可以返回一个实例,但是构造方法要是没有参数列表的,它相当于调用某个类的不带参数的构造方法,但是如果在初始化对象的时候要传参数,就要使用Constructor
Class<?> classType = String.class; Object obj = classType.newInstance();
b)先获得Class对象,然后通过该对象获得相应的Constructor对象,再通过该Constructor对象的newInstance()方法生成:
Class<?> classType = object.getClass(); Constructor cons = classType.getConstructor(new Class[]{}); Object obj = cons.newInstance(new Object[]{});
2)若想通过类的带参数的构造方法生成对象,只能使用下面一种方式
Class<?> classType = object.getClass(); Constructor cons = classType.getConstructor(new Class[]{String.class,int.class}); Object obj = cons.newInstance(new Object[]{"hello",3}); //以上的两行代码等价于下面一行 //Object obj2 = classType.newInstance();
反射访问私有(private)的方法
private 限制的方法没有办法在另外的类中使用,但可以使用反射进行使用。而getMethod()方法只能获取public的方法。如果要使用private的方法就要使用 getDeclaredMethod()方法。
1、获取privete方法
public class PrivateTest { private String sayHello(String name){ return "hello" + name; } } public class Test{ public static void main(String[] args) throws Exception{ PrivateTest obj = new PrivateTest(); Class<?> classType = obj.getClass(); Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class}); method.setAccessible(true); //压制java的访问控制检查 String str = (String)method.invoke(obj, new Object[]{"aaa"}); } }
2、改变private的属性
public class PrivateTest2 { private String name = "张三"; public String getName(){ return name; } } public class Test{ public static void main(String[] args) throws Exception{ PrivateTest2 obj = new PrivateTest2(); Class<?> classType = obj.getClass(); Field field = classType.getDeclaredField("name"); field.setAccessible(true); field.set(obj, "李四"); System.out.println(obj.getName()); } }
反射机制的优点与缺点
为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念。
- 静态编译:在编译时确定类型,绑定对象,即通过。
- 动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。
优点——可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中。
比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
缺点——对性能有影响。
使用反射基本上是一种解释操作,这类操作总是慢于只直接执行相同的操作。