反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性。rol.
通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。
程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射的核心是JVM在运行时才动态加载类或调用方法/访问属性,它不需要事先(写代码的时候或编译期)知道运行对象是谁。
Java反射框架主要提供以下功能:
重点:是运行时而不是编译时
反射的主要用途
获取某个Class对象的方法集合,主要有以下几个方法:
getDeclaredMethods()方法返回类或接口声明的所有方法,包括公共、保护、默认(包)访问和私有方法,但不包括继承的方法。
1
|
public Method[] getDeclaredMethods()
throws SecurityException
|
getMethods()方法返回某个类的所有公用(public)方法,包括其继承类的公用方法。
1
|
public Method[] getMethods()
throws SecurityException
|
getMethod方法返回一个特定的方法,其中第一个参数为方法名称,后面的参数为方法的参数对应Class的对象
下面我们通过一个例子来看这些方法 数组在Java里是比较特殊的一种类型,它可以赋值给一个Object Reference。下面我们看一看利用反射创建数组的例子:
1
2
3
4
5
6
7
8
9
10
11
12
|
public static void testArray() throws ClassNotFoundException {
Class> cls = Class.forName(
"java.lang.String");
Object array = Array.newInstance(cls,
25);
//往数组里添加内容
Array.set(array,
0,
"hello");
Array.set(array,
1,
"Java");
Array.set(array,
2,
"fuck");
Array.set(array,
3,
"Scala");
Array.set(array,
4,
"Clojure");
//获取某一项的内容
System.out.println(Array.get(array,
3));
}
|
其中的Array类为java.lang.reflect.Array类。我们通过Array.newInstance()创建数组对象,它的原型是:
1
2
3
4
|
public static Object newInstance(Class> componentType, int length)
throws NegativeArraySizeException {
return newArray(componentType, length);
}
|
而newArray()方法是一个Native方法,它在Hotspot JVM里的具体实现我们后边再研究,这里先把源码贴出来
1
2
|
private static native Object newArray(Class> componentType, int length)
throws NegativeArraySizeException;
|
源码目录:openjdk\hotspot\src\share\vm\runtime\reflection.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
arrayOop Reflection::reflect_new_array(oop element_mirror, jint length, TRAPS) {
if (element_mirror ==
NULL) {
THROW_0(vmSymbols::java_lang_NullPointerException());
}
if (length <
0) {
THROW_0(vmSymbols::java_lang_NegativeArraySizeException());
}
if (java_lang_Class::is_primitive(element_mirror)) {
Klass* tak = basic_type_mirror_to_arrayklass(element_mirror, CHECK_NULL);
return TypeArrayKlass::cast(tak)->allocate(length, THREAD);
}
else {
Klass* k = java_lang_Class::as_Klass(element_mirror);
if (k->oop_is_array() && ArrayKlass::cast(k)->dimension() >= MAX_DIM) {
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
return oopFactory::new_objArray(k, length, THREAD);
}
}
|
另外,Array类的set()和get()方法都为Native方法,在HotSpot JVM里分别对应Reflection::array_set和Reflection::array_get方法,这里就不详细解析了。