Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

在java环境中,反射机制允许程序在执行时获取某各类自身的定义信息,例如属性和方法等也可以实现动态创建类的对象、变更属性的内容或执行特定的方法的功能。从而使java具有动态语言的特性,增强了程序的灵活性和可移植性。

通过反射你可以获取类的Field、Method、Constructor、Superclass、Interface、Annotation以及泛型和类所在的包等信息。


【1】Reflection功能与API

Java反射机制提供的功能:

1.在运行时判断任意一个对象所属的类型;
2.在运行时构造任意一个类的对象;
3.在运行时判断任意一个类所具有的成员变量和方法;
4.在运行时调用任意一个对象的方法,甚至可以调用private方法。
5.生成动态代理。


Java反射机制API:

实现java反射机制的API在java.lang.reflect包下,如下所示:

1.java.lang.Class类:代表一个类;

2.java.lang.reflect.Field类:代表类的成员变量;

3.java.lang.reflect.Method类:代表类的方法;

4.java.lang.reflect.Constructor类:代表类的构造方法;

5.java.lang.reflectArray类:提供了动态创建数组以及访问数组的元素的静态方法。该类中所有方法都是静态的。


【2】Class类与加载机制

① class类定义

在Object类中定义了以下的方法,此方法将被所有子类继承:

public final Class getClass()

以上的方法返回值的类型是一个Class类,此类是Java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

Java反射机制(Reflection)简解与示例_反射获取私有属性

可以得到的信息:某个类的属性、方法和构造器、某个类到底实现了哪些接口。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。

Class本身也是一个类;
Class 对象只能由系统建立对象;
一个类在 JVM 中只会有一个Class实例 ;
一个Class对象对应的是一个加载到JVM中的一个.class文件;
每个类的实例都会记得自己是由哪个 Class 实例所生成;
通过Class可以完整地得到一个类中的完整结构 。


② class类常用方法

方法名

功能说明

​static Class<?> forName(String className)​

返回指定类名 name 的 Class 对象

​T newInstance​

调用缺省构造函数,返回该Class对象的一个实例

​String getName()​

返回此Class对象所表示的实体(类、接口、数组类、基本类型或void)名称

​native Class<? super T> getSuperclass()​

返回当前Class对象的父类的Class对象

​Class<?>[] getInterfaces()​

获取当前Class对象的接口

​ClassLoader getClassLoader()​

返回该类的类加载器

​Constructor<?>[] getConstructors()​

获取自身的所有的 public Constructor

​Field[] getFields()​

获取自身和父类的所有的 public Field

​Method[] getMethods()​

获取自身和父类所有的 public Method

​Field[] getDeclaredFields()​

获取自身所有的Field,但不包括从父类继承下来的属性

​Method[] getDeclaredMethods()​

获取自身所有的Method,但不包括从父类继承下来的方法

​Constructor<?>[] getDeclaredConstructors()​

获取自身所有的Constructor

​Field getField(String name)​

根据名字获取自身和父类的的 public Field

​Field getDeclaredField(String name)​

根据名字获取自身的属性

​Method getMethod(String name)​

根据名字获取自身和父类的的 public Method

​Method getDeclaredMethod(String name)​

根据名字获取自身的Method

​public Constructor<T> getConstructor(Class<?>... parameterTypes)​

获取自身的 public Constructor

​public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)​

根据名字获取自身的Constructor


这里Field示例总结如下:

# 获取自身和父类的所有的 public Field
public Field[] getFields() throws SecurityException {}

# 获取自身所有的Field,但不包括从父类继承下来的属性
public Field[] getDeclaredFields() throws SecurityException {}

# 根据名字获取自身和父类的 public Field
public Field getField(String name)

# 根据名字获取自身的 Field
public Field getDeclaredField(String name)

Field代码测试如下:

public class Father {

public int a;

private int b;

protected int f;

int g;

}
public class Son extends Father {

int c;

private String d;

protected float e;

public int h;

}
public class FieldTest {

public static void main(String[] args) {
Class cls = Son.class;

try {
Field c = cls.getDeclaredField("c");
System.out.println("getDeclaredField获取自身default :"+c);
Field d = cls.getDeclaredField("d");
System.out.println("getDeclaredField获取自身private :"+d);
Field e = cls.getDeclaredField("e");
System.out.println("getDeclaredField获取自身protected :"+e);
Field h = cls.getDeclaredField("h");
System.out.println("getDeclaredField获取自身public :"+h);

// 父类public获取不到
// Field a = cls.getDeclaredField("a");
// System.out.println("getDeclaredField获取父类public :"+a);
// 父类private获取不到
// Field b = cls.getDeclaredField("b");
// System.out.println("getDeclaredField获取父类private :"+b);
// 父类protected获取不到
// Field f = cls.getDeclaredField("f");
// System.out.println("getDeclaredField获取父类protected :"+f);
// 父类default获取不到
// Field g = cls.getDeclaredField("g");
// System.out.println("getDeclaredField获取父类default :"+g);

} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getDeclaredField "+e.getMessage());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getDeclaredField "+e.getMessage());
}

try {
// 自身default获取不到
// Field c = cls.getField("c");
// System.out.println("getField获取自身default :"+c);
// 自身private获取不到
// Field d = cls.getField("d");
// System.out.println("getField获取自身private :"+d);
// 自身protected获取不到
// Field e = cls.getField("e");
// System.out.println("getField获取自身protected :"+e);
Field h = cls.getField("h");
System.out.println("getField获取自身public :"+h);

Field a = cls.getField("a");
System.out.println("getField获取父类public :"+a);
// 父类private获取不到
// Field b = cls.getField("b");
// System.out.println("getField获取父类private :"+b);
// 父类protected获取不到
// Field f = cls.getField("f");
// System.out.println("getField获取父类protected :"+f);
//父类default获取不到
// Field g = cls.getField("g");
// System.out.println("getField获取父类default :"+g);

} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getField "+e.getMessage());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getField "+e.getMessage());
}

// 获取自身所有,不包括父类属性
Field[] filed1 = cls.getDeclaredFields();

for ( Field f : filed1 ) {
System.out.println("Declared Field :"+f.getName());
}
// 获取所有public属性,包括父类的
Field[] filed2 = cls.getFields();

for ( Field f : filed2 ) {
System.out.println("Field :"+f.getName());
}

}

}

Field测试结果如下:

getDeclaredField获取自身default :int com.web.test.Son.c
getDeclaredField获取自身private :private java.lang.String com.web.test.Son.d
getDeclaredField获取自身protected :protected float com.web.test.Son.e
getDeclaredField获取自身public :public int com.web.test.Son.h
getField获取自身public :public int com.web.test.Son.h
getField获取父类public :public int com.web.test.Father.a
Declared Field :c
Declared Field :d
Declared Field :e
Declared Field :h
Field :h
Field :a

Method示例总结如下:

# 获取自身和父类的所有的 public Method
public Method[] getMethods() throws SecurityException {

# 获取自身所有的Method,但不包括从父类继承下来的方法
public Method[] getDeclaredMethods() throws SecurityException {}

# 根据名字获取自身和父类的 public Method
public Method getMethod(String name, Class<?>... parameterTypes)

# 根据名字获取自身的 Method
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

Method代码测试如下:

public class Father {

public int a;

private int b;

protected int f;

int g;

public void methodA(){
System.out.println("父类public methodA");
}
private void methodB(){
System.out.println("父类private methodB");
}
protected void methodF(){
System.out.println("父类protected methodF");
}
void methodG(){
System.out.println("父类default methodG");
}

}

public class Son extends Father {

int c;

private int d;

protected float e;

public int h;

void methodC(){
System.out.println("自身default methodC");
}
private void methodD(){
System.out.println("自身private methodD");
}
protected void methodE(){
System.out.println("自身protected methodE");
}
public void methodH(){
System.out.println("自身public methodH");
}
}

public class MethodTest {

public static void main(String[] args) {
Class cls = Son.class;

try {
Method c = cls.getDeclaredMethod("methodC");
System.out.println("getDeclaredMethod获取自身default :"+c);
Method d = cls.getDeclaredMethod("methodD");
System.out.println("getDeclaredMethod获取自身private :"+d);
Method e = cls.getDeclaredMethod("methodE");
System.out.println("getDeclaredMethod获取自身protected :"+e);
Method h = cls.getDeclaredMethod("methodH");
System.out.println("getDeclaredMethod获取自身public :"+h);

// 父类public获取不到
// Method a = cls.getDeclaredMethod("methodA");
// System.out.println("getDeclaredMethod获取父类public :"+a);
// 父类private获取不到
// Method b = cls.getDeclaredMethod("methodB");
// System.out.println("getDeclaredMethod获取父类private :"+b);
// 父类protected获取不到
// Method f = cls.getDeclaredMethod("methodF");
// System.out.println("getDeclaredMethod获取父类protected :"+f);
// 父类default获取不到
// Method g = cls.getDeclaredMethod("methodG");
// System.out.println("getDeclaredMethod获取父类default :"+g);

} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getDeclaredMethod "+e.getMessage());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getDeclaredMethod "+e.getMessage());
}

try {
// 自身default获取不到
// Method c = cls.getMethod("methodC");
// System.out.println("getMethod获取自身default :"+c);
// 自身private获取不到
// Method d = cls.getMethod("methodD");
// System.out.println("getMethod获取自身private :"+d);
// 自身protected获取不到
// Method e = cls.getMethod("methodE");
// System.out.println("getMethod获取自身protected :"+e);
Method h = cls.getMethod("methodH",null);
System.out.println("getMethod获取自身public :"+h);

Method a = cls.getMethod("methodA",null);
System.out.println("getMethod获取父类public :"+a);
// 父类private获取不到
// Method b = cls.getMethod("methodB");
// System.out.println("getMethod获取父类private :"+b);
// 父类protected获取不到
// Method f = cls.getMethod("methodF");
// System.out.println("getMethod获取父类protected :"+f);
//父类default获取不到
// Method g = cls.getMethod("methodG");
// System.out.println("getMethod获取父类default :"+g);

} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getMethod "+e.getMessage());
}catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getMethod "+e.getMessage());
}

// 获取自身所有,不包括父类方法
Method[] method1 = cls.getDeclaredMethods();

for ( Method m : method1 ) {
System.out.println("Declared Method :"+m.getName());
}
// 获取所有public方法,包括父类的
Method[] method2 = cls.getMethods();

for ( Method m : method2 ) {
System.out.println("Method :"+m.getName());
}

}

}

Method测试结果如下:

getDeclaredMethod获取自身default :void com.web.test.Son.methodC()
getDeclaredMethod获取自身private :private void com.web.test.Son.methodD()
getDeclaredMethod获取自身protected :protected void com.web.test.Son.methodE()
getDeclaredMethod获取自身public :public void com.web.test.Son.methodH()
getMethod获取自身public :public void com.web.test.Son.methodH()
getMethod获取父类public :public void com.web.test.Father.methodA()
Declared Method :methodC
Declared Method :methodD
Declared Method :methodH
Declared Method :methodE
Method :methodH
Method :methodA
Method :wait
Method :wait
Method :wait
Method :equals
Method :toString
Method :hashCode
Method :getClass
Method :notify
Method :notifyAll

Constructor总结如下:

# 获取自身所有的 public Constructor
public Constructor<?>[] getConstructors() throws SecurityException {}

# 获取自身所有的Constructor--构造器不能继承
public Constructor<?>[] getDeclaredConstructors() throws SecurityException {}

# 获取自身 public Constructor
public Constructor<T> getConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {}

# 获取自身的 Constructor
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException {

Constructor测试代码如下:

public class Father {

public int a;

private int b;

protected int f;

int g;

public void methodA(){
System.out.println("父类public methodA");
}
private void methodB(){
System.out.println("父类private methodB");
}
protected void methodF(){
System.out.println("父类protected methodF");
}
void methodG(){
System.out.println("父类default methodG");
}

public Father(){
super();
}
private Father(int b){
super();
this.b = b;
}
protected Father(int f,int b ){
super();
this.f = f;
this.b = b;
}
Father(int f,int b,int g ){
super();
this.f = f;
this.b = b;
this.g = g;
}
public Father(int a,int f,int b,int g ){
super();
this.a = a;
this.f = f;
this.b = b;
this.g = g;
}
}

public class Son extends Father {

int c;

private int d;

protected float e;

public int h;

void methodC(){
System.out.println("自身default methodC");
}
private void methodD(){
System.out.println("自身private methodD");
}
protected void methodE(){
System.out.println("自身protected methodE");
}
public void methodH(){
System.out.println("自身public methodH");
}

public Son(){
super();
}
private Son(int d){
super();
this.d = d;
}
protected Son(int d,int e ){
super();
this.e = e;
this.d = d;
}
Son(int c,int d,int e ){
super();
this.c = c;
this.d = d;
this.e = e;
}
}

public class ConstructorTest {

public static void main(String[] args) {
Class cls = Son.class;

try {
Constructor<Son> c = cls.getDeclaredConstructor(int.class,int.class,int.class);
System.out.println("getDeclaredConstructor获取自身default :"+c);
Constructor<Son> d = cls.getDeclaredConstructor(int.class);
System.out.println("getDeclaredConstructor获取自身private :"+d);
Constructor<Son> e = cls.getDeclaredConstructor(int.class,int.class);
System.out.println("getDeclaredConstructor获取自身protected :"+e);
Constructor<Son> h = cls.getDeclaredConstructor();
System.out.println("getDeclaredConstructor获取自身public :"+h);

} catch (NoSuchMethodException e) {
e.printStackTrace();
System.out.println("getDeclaredConstructor "+e.getMessage());
} catch (SecurityException e) {
e.printStackTrace();
System.out.println("getDeclaredConstructor "+e.getMessage());
}

try {

// 自身default获取不到
// Constructor<Son> c = cls.getConstructor(int.class,int.class,int.class);
// System.out.println("getConstructor获取自身default :"+c);
// 自身private获取不到
// Constructor<Son> d = cls.getConstructor(int.class);
// System.out.println("getConstructor获取自身private :"+d);
// 自身protected获取不到
// Constructor<Son> e = cls.getConstructor(int.class,int.class);
// System.out.println("getConstructor获取自身protected :"+e);
Constructor<Son> h = cls.getConstructor();
System.out.println("getConstructor获取自身public :"+h);

// 父public can't get
// Constructor constructor = cls.getConstructor(int.class,int.class,int.class,int.class);
// System.out.println("getConstructor获取父public :"+constructor);

} catch (SecurityException | NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("getConstructor "+e.getMessage());
}

// 获取自身所有 Constructor
Constructor[] constructors1 = cls.getDeclaredConstructors();

for ( Constructor c : constructors1 ) {
System.out.println("Declared Constructor :"+c.getName());
}
// 获取自身所有public Constructor
Constructor[] constructors2 = cls.getConstructors();

for ( Constructor c : constructors2 ) {
System.out.println("Constructor :"+c.getName());
}
}
}

Constructor测试结果如下:

getDeclaredConstructor获取自身default :com.web.test.Son(int,int,int)
getDeclaredConstructor获取自身private :private com.web.test.Son(int)
getDeclaredConstructor获取自身protected :protected com.web.test.Son(int,int)
getDeclaredConstructor获取自身public :public com.web.test.Son()
getConstructor获取自身public :public com.web.test.Son()
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Declared Constructor :com.web.test.Son
Constructor :com.web.test.Son

③ 实例化类的四种方法

  • 已知具体的类,通过类的class属性获取
Class clazz = String.class
# 该方法最为安全可靠,程序性能最高
  • 已知某个类的实例,调用该实例的getClass()方法获 取Class对象
Class clazz = person.getClass();
  • 已知一个类的全类名,且该类在类路径下,可通过 Class类的静态方法forName()获取
Class clazz = Class.forName(“java.lang.String”);
# 可能抛出ClassNotFoundException
  • ClassLoader
ClassLoader cl = this.getClass().getClassLoader();
Class clazz = cl.loadClass(“类的全类名”);

【3】类的加载过程

当程序主动使用某个类时,如果该类还未被加载到内存中,则系统会通过如下三个步骤来对该类进行初始化。

Java反射机制(Reflection)简解与示例_java_02
Java反射机制(Reflection)简解与示例_父类_03


【4】ClassLoader

类加载器是用来把类(class)装载进内存的。

JVM 规范定义了两种类型的类加载器:启动类加载器(bootstrap)和用户自定义加载器(user-defined class loader)。

JVM在运行时会产生3个类加载器组成的初始化加载器层次结构 ,如下图所示:

Java反射机制(Reflection)简解与示例_反射获取私有属性_04

实例代码如下:

//1.获取一个系统类加载器
ClassLoader classloader = ClassLoader.getSystemClassLoader();
System.out.println(classloader);

//2.获取系统类加载器的父类加载器,即扩展类加载器
classloader = classloader.getParent();
System.out.println(classloader);

//3.获取扩展类加载器的父类加载器,即引导类加载器
classloader = classloader.getParent();
System.out.println(classloader);

//4.测试当前类由哪个类加载器进行加载
classloader = Class.forName("exer2.ClassloaderDemo").getClassLoader();
System.out.println(classloader);

实例demo–动态创建数组对象:

/*,对数组元素赋值和取值*/
public void test(){
Class c = Class.forName("java.lang.String");
//create a String type Array,the length is 10
Object arr = Array.newInstance(c,10);
//at the index =5 ,assignment the parameter value
Array.set(arr,5,"this is a test");
//get the index=5 value
String s = (String)Array.get(arr,5);
System.out.println(s);
}

【5】使用反射获取私有属性/方法

使用Class类中的方法可以获得该类中的所有Constructor对象,Method对象,和Field对象。

但是无法访问私有化的构造方法,普通方法,和私有属性,此时我们可以使用他们继承父类(AccessibleObject)中的​​setAccessible()​​方法,来设置或取消访问检查,以达到访问私有对象的目的。

如下示例,获取私有属性(方法类同):

Field[] fields = Test.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
try {
System.out.println(fields[i].get(test));
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

其他点击查看反射详解参考