概念和用处
Java 程序中的很多对象在运行时都会出现两种类型:编译时类型和运行时类型。例如:person p = new Student(); 产生的p变量在编译时的类型为Person,运行时的类型为Student;假设在运行时接受到一个对象,改对象编译时类型是Object,但程序又需要调用该对象运行时的方法。解决方法:
(1)假设在编译时和运行时都完全知道类型的具体信息,直接使用instanceof 云算法进行判断,再利用强制类型转换成运行时的变量;
(2)假设编译时根本无法预知该对象和类属于哪些类,程序只依靠运行时的信息来发现该对象和类的真实信息,这就使用到了反射。
在深入理解类加载机制(1)中,介绍过每个类被加载后,系统就会为该类生成一个Class对象。通过这个Class对象,就可以访问到JVM中的这个类。
Java反射机制的定义为:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反射机制。
很多框架都是利用反射机制来设计的。上面反射机制的定义还是很言简意赅的。因为反射可以在运行时加载、探知、使用完全未知的类,你只要给我一个路径就可以了,我通过这个路径拿到我需要的东西,我的操作与你无关了,灵活性更高了,类之间的耦合性也就降低了。同时我们可以获取到类的私有信息,破坏了类的封装,使类变得不安全。使用反射还会降低程序性能。所以说使用反射优点突出,缺点同样突出。
获得Class对象的三种方式
(1)利用Class类的forName(String clazzName)静态方法,传入字符串参数(类的全限定路径(必须添加完整的包名));
Class.forName("cn.edu.uestc.collection.A");
(2)每个类都有一个class属性,调用此属性来获取类对应的Class对象。例如:Person.class将会返回Person类对应的Class对象;class是类属性,必须有声明一个Class变量;
Class a = A.class;
(3)调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个native方法。所以所有的Java对象可调用此方法,返回调用对象的Class对象。
public final native Class<?> getClass();
A aa = new A();
aa.getClass();
一个小点:调用有返回值的函数,可以不接收其返回值。
相比较而言,第二种方式有优势:
1)代码更安全。第一种forName()方式可能会抛出:ClassNotFoundException异常,必须进行捕获或抛出,要不然编译(编译期间检测)不通过;
2)程序性能好,第二种方法无需调用方法,性能更好。
从Class中获取信息
Class类提供了大量的实例方法来获取该Class对象所对应的类的详细信息。在java.lang.reflect包下,定义了一些类,用来表示类的构造函数,Field,和成员方法Method。
在Class类中,包含了很多方法,功能非常丰富,来获得该类包含的:构造器,成员函数method,成员属性,内部类,注释等。
首先我们要知道Java里实现反射的那个类是java.lang.reflect。我们查看API在类摘要里主要有以下四个类:
① java.lang.reflect.AccessibleObject
② java.lang.reflect.Constructor<T>
③ java.lang.reflect.Field
④ java.lang.reflect.Method
其中AccessibleObject 是另外三个类的基类。我们接下来涉及的主要就是这几个类。
下边具体介绍一下获得类构造器,方法和属性(Field)的Class方法。
获得Class对应类所包含的构造器:
会抛异常NoSuchMethodException或SecurityException,需要处理
//返回Class对象对应类的指定public构造器
public Constructor<T> getConstructor(Class<?>... parameterTypes)
//返回Class对象对应类的所有public构造器
public Constructor<?>[] getConstructors()
//返回Class对象对应类的指定构造器,与访问权限无关
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
//返回Class对象对应类的所有构造器,与访问权限无关
public Constructor<?>[] getDeclaredConstructors()
获得Class对应类所包含的方法:
//返回Class对象对应类的指定public方法
public Method<T> getMethod (Class<?>... parameterTypes)
//返回Class对象对应类的所有public方法
public Method<?>[] Method()
//返回Class对象对应类的指定方法,与访问权限无关
public Method<T> getDeclaredMethod(Class<?>... parameterTypes)
//返回Class对象对应类的所有方法,与访问权限无关
public Method<?>[] getDeclaredMethod()
获得Class对应类所包含的Field:
//返回Class对象对应类的指定publid Field
public Field<T> getField(Class<?>... parameterTypes)
//返回Class对象对应类的所有public Field
public Field<?>[] getField()
//返回Class对象对应类的指定Field,与访问权限无关
public Field<T> getDeclaredField(Class<?>... parameterTypes)
//返回Class对象对应类的所有Field,与访问权限无关
public Field<?>[] getDeclaredField()
具体使用代码先不贴,放在下篇使用反射生成并操作对象来写。