1.为什么使用反射?
java中反射是在运行中动态的加载进入。有个很大的好处就是可以节省很多资源。为什么这么说呢,首先我们来说一下jvm,jvm是java的虚拟机,java之所以支持跨平台就是因为java虚拟机的存在。程序你有如下语句 Object o=new Object();运行起来的时候,java的虚拟机会首先启动。将你的java文件编译成 .class文件。加载进入你jvm的内存之中。你的类Object会加载进入方法区,这时候会生成个类的类型对象(即class类的对象)加载到堆中,作为方法区类的数据结构的接口。jvm创建对象时会看你的类是否加载好,加载好了便生成你的类的对象。然而在大型工程项目中,有很多可能暂时用不到,所以我们没必要把每一个类都生成对象。而反射机制正是解决这了这个问题。
为什么要用反射机制?直接创建对象不就可以了吗?这就涉及到了动态与静态的概念。
静态编译:在编译时确定类型,绑定对象。
动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,由此降低类之间的藕合性。
一句话,反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中,它的灵活性就表现的十分明显。
比如,一个大型的软件,不可能一次就把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。
2.什么是反射机制?
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
3.反射机制的主要功能?
在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
4.获取Class对象方式?
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取字节码文件对象的三种方式。
1、Class clazz1 = Class.forName("全限定类名"); //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
2、Class clazz2 = Person.class; //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
3、Class clazz3 = p.getClass(); //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段
5.反射机制的使用
5.1获取对象实例
package reflect; public class Test { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { Class class1=Class.forName("reflect.User");//获取User类的字节码对象 User user=(User) class1.newInstance();//创建User实例,使用user的无参构造幻术 } }
5.2获取指定构造器方法。constructor 如果没有无参构造,只有有参构造如何创建实例呢?
Class class1=Class.forName("reflect.User"); Constructor constructor=class1.getDeclaredConstructor(String.class);//获取有参构造器对象 User user=(User) constructor.newInstance("xiaoming");//通过构造器创建有参实例
总结上面创建实例对象:Class类的newInstance()方法是使用该类无参的构造函数创建对象, 如果一个类没有无参的构造函数, 就不能这样创建了,可以调用Class类的 getConstructor(String.class)方法获取一个指定的构造函数然后再调用Constructor类的newInstance("张三")方法创建对象。
5.3获取成员变量并使用
package reflect; import java.lang.reflect.Field; public class Test { public static void main(String[] args) throws Exception{ Class<?> class1=Class.forName("reflect.User"); User user=(User) class1.newInstance(); Field field=class1.getDeclaredField("name");//获得成员变量的名字 field.setAccessible(true);//因为成员变量为私有的,要设置可见性 field.setInt(user, 5);//对属性进行赋值操作 System.out.println(field.getInt(user)); } }
5.4获得成员方法并使用
package reflect; import java.lang.reflect.Method; public class Test { public static void main(String[] args) throws Exception{ Class<?> class1=Class.forName("reflect.User"); User user=(User) class1.newInstance(); Method method=class1.getMethod("test"); method.invoke(user); } }