(typora直接复制过来的排版崩了大半尤其是表格)
Java是静态语言,在运行期间,程序结构和变量类型是不能变的。
反射机制reflection,可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
在运行时构造任意一个类的对象
在运行时获取任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法(属性)
生成动态代理
有了反射机制,Java就有了动态编译的特点,也就是在运行时才确定类型,绑定对象。如果没有动态编译能力的话,每次改变程序,都需要重新编译Java程序。
要运用反射机制,涉及到的类是 Class 类(与关键字class区分开)。
public final class Class<T>
extends Object
implements Serializable, GenericDeclaration, Type, AnnotatedElement
Class没有公共的构造方法,由JVM在加载一个类的时候自动生成。每个被加载的类都有一个对应的Class类对象,这个对象记录着加载类的信息。
要得到这个Class对象从而获得目标类的信息,有三种方法。
- Class example = SomeClassObject.getClass();//getClass是继承自Object的,每个类都有。
- Class example2 = SomeClass.class;//每个对象都有class属性,包括基本数据类型
- Class example3 = Class.forName("SomeClass");//最常用的
static Class<?> forName(Module module, String name) Returns the Class with the given binary name in the given module.
static Class<?> forName(String className) Returns the Class object associated with the class or interface with the given string name.
static Class<?> forName(String name, boolean initialize, ClassLoader loader) Returns the Class object associated with the class or interface with the given string name, using the given class loader.
通过Class的get方法,具体来说,可以得到:
类的注解:AnnotatedType[] getAnnotatedInterfaces(),AnnotatedType getAnnotatedSuperclass(),A getAnnotation(Class annotationClass),Annotation[] getAnnotations(),A[] getAnnotationsByType(Class annotationClass)
类的名称:String getName(),String getCanonicalName(),String getSimpleName()。前两个的不同体现在内部类中,第三个则是返回类的简称。
类的构造方法:Constructor<?>[] getConstructors()……
类的成员变量:Field[] getFields()……
类的成员方法:Method[] getMethods()……
以及一些判断方法 isArray(),isInterface()……
……方法可以说是很多了
还有一个实例化方法
T newInstance() Deprecated. This method propagates any exception thrown by the nullary constructor, including a checked exception. Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler. The Constructor.newInstance method avoids this problem by wrapping any exception thrown by the constructor in a (checked) InvocationTargetException. The call clazz.newInstance() can be replaced by clazz.getDeclaredConstructor().newInstance() The latter sequence of calls is inferred to be able to throw the additional exception types InvocationTargetException and NoSuchMethodException. Both of these exception types are subclasses of ReflectiveOperationException.
Object obj = Class.forName("SomeClass").newInstance();
或者
Class\<SomeClass> obj = Class.forName("SomeClass");
SomeClass newObj = obj.newInstance();
另外,泛型有个擦除特性,所以可以利用反射在运行期间绕过泛型的检查,比如String类型的List,可以用反射在运行期间加入一个Integer。