Java反射学习实践

简单来说,Java中通过反射,可以在运行时获得程序自身的信息,并且可以操作类或对象的内部属性。

Reflection enables Java code to discover information about the fields, methods and constructors of loaded classes, and to use reflected fields, methods, and constructors to operate on their underlying counterparts, within security restrictions.
The API accommodates applications that need access to either the public members of a target object (based on its runtime class) or the members declared by a given class. It also allows programs to suppress default reflective access control.

上述为Oracle官方的反射解释。

Java反射提供的功能:

  • 1.在运行时判断任意一个对象所属的类;
  • 2.在运行时构造任意一个类的对象;
  • 3.在运行时判断任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法);
  • 4.在运行时调用任意一个对象的方法

class类

提到反射,我们需要先声明下Java中的class类,as we know,所有的java类均继承了Object类,在Object类中定义了一个getClass()方法,该方法返回一个类型为Class的对象。如下

1
Class testc = textField.getClass();//textField为JTextField对象

通过testc对象我们可以访问到JTextFiel的描述信息:主要描述信息如下

访问方法 返回值类型 说明
getPackage() Package对象 获得该类的存放路径
getName() String对象 该类的名称
getSuperClass() Class对象 获得该类继承的类
getInterface() Class数组 获得该类实现的所有接口
getConstructors() Constructor数组 获得所有权限为public的构造方法
getConstructor(Class<?>…types) Constructor对象 获得权限为public的指定的构造方法
getDeclaredConstructors() Constructor数组 获得所有的构造方法,按声明顺序返回
getDeclaredConstructor(Class<?>…types) Constructor对象 获得指定的构造方法
getMethods() Method数组 获得所有权限为Public的方法
getMethod(String name, Class<?>…types) Method对象 获得权限为Public的指定的方法
getDeclaredMethods() Method数组 获得所有的方法,按声明顺序返回
getDeclaredMethod(String name, Class<?>…types) Method对象 获得指定的方法
getFields() Field数组 获得所有权限为Public的成员变量
getField(String name) Field对象 获得权限为Public的指定的成员变量
getDeclaredFields() Field数组 获得所有的成员变量
getDeclaredField(String name) Method对象 获得指定的成员变量
getClasses() Class数组 获得所有权限为public的内部类
getDeclaredClasses() Class数组 获得所有内部类
getDeclaringClass() Class对象 如果该类为内部类,则返回它的成员类,否则返回null

说明:getClasses()和getMethods()会包含父类中权限为public的成员变量和方法

获得Class的其他方法

1
2
3
4
5
//第一种方式:
Class testc = Class.forName("JTextField");
//第二种方式:
//java中每个类型都有class 属性.
Class testc = JTextField.class;

java提供的反射类

java.lang.Class;
java.lang.reflect.Constructor; java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;

获得Class对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.mrx.testreflection;
/**
* 反射实践类
* 2017年6月6日21:33:22
* @author Mrx
*/
public class TestReflection {
public static void main(String[] args) {
/**获得class的方式**/
Class c1 = null;
Class c2 = null;
Class c3 = null;
try {
c1 = Class.forName("com.mrx.testreflection.TestReflection");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
c2 = new TestReflection().getClass();
c3 = TestReflection.class;
System.out.println(c1.getName());
System.out.println(c2.getName());
System.out.println(c3.getName());
}
}

打印结果为

1
2
3
com.mrx.testreflection.TestReflection
com.mrx.testreflection.TestReflection
com.mrx.testreflection.TestReflection

获得对象的父类和实现的接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.mrx.testreflection;
import java.io.Serializable;
/**
* 反射实践类
* 2017年6月6日21:33:22
* @author Mrx
*/
public class TestReflection implements Serializable {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> clazz = Class.forName("com.mrx.testreflection.TestReflection");
// 取得父类
Class<?> parentClass = clazz.getSuperclass();
System.out.println("父类为:" + parentClass.getName());
// 获取所有的接口
Class<?> intes[] = clazz.getInterfaces();
System.out.println("实现的接口有:");
for (int i = 0; i < intes.length; i++) {
System.out.println((i + 1) + ":" + intes[i].getName());
}
}
}

打印结果为

1
2
父类为:java.lang.Object
实现的接口有:1:java.io.Serializable

获得类中的构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> class1 = null;
class1 = Class.forName("com.mrx.testreflection.Person");
Constructor<?> cons[] = class1.getConstructors();
// 查看每个构造方法需要的参数
for (int i = 0; i < cons.length; i++) {
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for (int j = 0; j < clazzs.length; j++) {
if (j == clazzs.length - 1)
System.out.print(clazzs[j].getName());
else
System.out.print(clazzs[j].getName() + ",");
}
System.out.println(")");
}
}
}
class Person {
private String name;
public int age;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public Person(int age) {
super();
this.age = age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
}

打印结果为

1
2
3
4
cons[0] (java.lang.String,int)
cons[1] (int)
cons[2] (java.lang.String)
cons[3] ()

###实例化一个对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
public static void main(String[] args) throws Exception {
Class<?> class1 = null;
class1 = Class.forName("com.mrx.testreflection.Person");
Person person = (Person) class1.newInstance();
person.age = 20;
person.name = "Lilei";
System.out.println(person);
Constructor<?> cons[] = class1.getConstructors();
// 查看每个构造方法需要的参数
for (int i = 0; i < cons.length; i++) {
Class<?> clazzs[] = cons[i].getParameterTypes();
System.out.print("cons[" + i + "] (");
for (int j = 0; j < clazzs.length; j++) {
if (j == clazzs.length - 1)
System.out.print(clazzs[j].getName());
else
System.out.print(clazzs[j].getName() + ",");
}
System.out.println(")");
}
//cons[0] (java.lang.String,int)
//cons[1] (int)
//cons[2] (java.lang.String)
//cons[3] ()
Person person1 = (Person) cons[0].newInstance("Hanmeimei", 18);
System.out.println(person1);
Person person2= (Person) cons[1].newInstance(38);
System.out.println(person2);
}
}
class Person {
public String name;
public int age;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
public Person(int age) {
super();
this.age = age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}

打印结果为

1
2
3
4
5
6
7
Person [name=Lilei, age=20]
cons[0] (java.lang.String,int)
cons[1] (int)
cons[2] (java.lang.String)
cons[3] ()
Person [name=Hanmeimei, age=18]
Person [name=null, age=38]

获取类的全部属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
public String hello = "reflection";
private String reflection = "hello";
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.mrx.testreflection.TestReflection");
System.out.println("===============全部成员变量===============");
// 取得本类的全部成员变量
Field[] field = clazz.getDeclaredFields();
for (int i = 0; i < field.length; i++) {
// 权限修饰符
int mo = field[i].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = field[i].getType();
System.out.println(priv + " " + type.getName() + " "
+ field[i].getName() + ";");
}
System.out.println("===============public成员变量===============");
// 取得本类的public成员变量
Field[] filed1 = clazz.getFields();
for (int j = 0; j < filed1.length; j++) {
// 权限修饰符
int mo = filed1[j].getModifiers();
String priv = Modifier.toString(mo);
// 属性类型
Class<?> type = filed1[j].getType();
System.out.println(priv + " " + type.getName() + " "
+ filed1[j].getName() + ";");
}
}
}

打印结果为

1
2
3
4
5
===============全部成员变量===============
public java.lang.String hello;
private java.lang.String reflection;
===============public成员变量===============
public java.lang.String hello;

获取类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
public String hello = "reflection";
private String reflection = "hello";
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.mrx.testreflection.TestReflection");
Method method[] = clazz.getMethods();
for (int i = 0; i < method.length; ++i) {
Class<?> returnType = method[i].getReturnType();
Class<?> para[] = method[i].getParameterTypes();
int temp = method[i].getModifiers();
System.out.print(Modifier.toString(temp) + " ");
System.out.print(returnType.getName() + " ");
System.out.print(method[i].getName() + " ");
System.out.print("(");
for (int j = 0; j < para.length; ++j) {
System.out.print(para[j].getName() + " " + "arg" + j);
if (j < para.length - 1) {
System.out.print(",");
}
}
Class<?> exce[] = method[i].getExceptionTypes();
if (exce.length > 0) {
System.out.print(") throws ");
for (int k = 0; k < exce.length; ++k) {
System.out.print(exce[k].getName() + " ");
if (k < exce.length - 1) {
System.out.print(",");
}
}
} else {
System.out.print(")");
}
System.out.println();
}
}
}

打印结果为

1
2
3
4
5
6
7
8
9
10
public static void main ([Ljava.lang.String; arg0) throws java.lang.Exception
public final void wait () throws java.lang.InterruptedException
public final void wait (long arg0,int arg1) throws java.lang.InterruptedException
public final native void wait (long arg0) throws java.lang.InterruptedException
public boolean equals (java.lang.Object arg0)
public java.lang.String toString ()
public native int hashCode ()
public final native java.lang.Class getClass ()
public final native void notify ()
public final native void notifyAll ()

反射调用类的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
public String hello = "reflection";
private String reflection = "hello";
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.mrx.testreflection.TestReflection");
Method method = clazz.getMethod("eatMeat");
method.invoke(clazz.newInstance());
method = clazz.getMethod("eat", String.class);
method.invoke(clazz.newInstance(), "shit");
}
public void eatMeat() {
System.out.println("Java 反射机制 - 调用类的方法eatMeat");
}
public void eat(String food) {
System.out.println("Java 反射机制 - 调用类的方法eat"+food);
}
}

打印结果

1
2
Java 反射机制 - 调用类的方法eatMeat
Java 反射机制 - 调用类的方法eatshit

反射操作类的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* 反射实践类 2017年6月6日21:33:22
*
* @author Mrx
*/
public class TestReflection implements Serializable {
private String proprety = null;
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("com.mrx.testreflection.TestReflection");
Object obj = clazz.newInstance();
// 可以直接对 private 的属性赋值
Field field = clazz.getDeclaredField("proprety");
field.setAccessible(true);
field.set(obj, "Java反射机制");
System.out.println(field.get(obj));
}
}

打印结果

1
Java反射机制

反射的动态代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
//定义项目接口
interface Subject {
public String say(String name, int age);
}
// 定义真实项目
class RealSubject implements Subject {
public String say(String name, int age) {
return name + " " + age;
}
}
class MyInvocationHandler implements InvocationHandler {
private Object obj = null;
public Object bind(Object obj) {
this.obj = obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object temp = method.invoke(this.obj, args);
return temp;
}
}
/**
* 在java中有三种类类加载器。
*
* 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
*
* 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
*
* 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
*
* 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
*
*
*/
public class TestReflection implements Serializable {
private String proprety = null;
public static void main(String[] args) throws Exception {
MyInvocationHandler demo = new MyInvocationHandler();
Subject sub = (Subject) demo.bind(new RealSubject());
String info = sub.say("Rollen", 20);
System.out.println(info);
}
}

打印结果为

1
Rollen 20

反射的应用

在泛型为Integer的ArrayList中存放一个String类型的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
public class TestReflection implements Serializable {
private String proprety = null;
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
Method method = list.getClass().getMethod("add", Object.class);
method.invoke(list, "Java反射机制实例。");
System.out.println(list.get(0));
}
}

打印结果为

1
Java反射机制实例。

反射修改数组信息和大小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
public class TestReflection implements Serializable {
private String proprety = null;
public static void main(String[] args) throws Exception {
int[] temp = { 1, 2, 3, 4, 5 };
Class<?> demo = temp.getClass().getComponentType();
System.out.println("数组类型: " + demo.getName());
System.out.println("数组长度 " + Array.getLength(temp));
System.out.println("数组的第一个元素: " + Array.get(temp, 0));
Array.set(temp, 0, 100);
System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
int[] newTemp = (int[]) arrayInc(temp, 15);
print(newTemp);
String[] atr = { "a", "b", "c" };
String[] str1 = (String[]) arrayInc(atr, 8);
print(str1);
}
// 修改数组大小
public static Object arrayInc(Object obj, int len) {
Class<?> arr = obj.getClass().getComponentType();
Object newArr = Array.newInstance(arr, len);
int co = Array.getLength(obj);
System.arraycopy(obj, 0, newArr, 0, co);
return newArr;
}
// 打印
public static void print(Object obj) {
Class<?> c = obj.getClass();
if (!c.isArray()) {
return;
}
System.out.println("数组长度为: " + Array.getLength(obj));
for (int i = 0; i < Array.getLength(obj); i++) {
System.out.print(Array.get(obj, i) + " ");
}
System.out.println();
}
}

打印结果为

1
2
3
4
5
6
7
8
数组类型: int
数组长度 5
数组的第一个元素: 1
修改之后数组第一个元素为: 100
数组长度为: 15
100 2 3 4 5 0 0 0 0 0 0 0 0 0 0
数组长度为: 8
a b c null null null null null

将反射机制应用于改善简单工厂模式的缺陷

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.mrx.testreflection;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
interface Animal {
public abstract void eat();
}
class Wolf implements Animal {
public void eat() {
System.out.println("wolf eat meat");
}
}
class Dog implements Animal {
public void eat() {
System.out.println("dog eat shit");
}
}
class Factory {
public static Animal getInstance(String ClassName) {
Animal animal = null;
try {
animal = (Animal) Class.forName(ClassName).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return animal;
}
}
/**
* 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
* Java 工厂模式可以参考
* http://baike.xsoftlab.net/view/java-factory-pattern
*
* 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
*
* 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
*
* java 读取 properties 配置文件 的方法可以参考
* http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
*
*/
public class TestReflection implements Serializable {
public static void main(String[] args) throws Exception {
Animal f = null;
f = Factory.getInstance("com.mrx.testreflection.Dog");
if (f != null) {
f.eat();
}
f = Factory.getInstance("com.mrx.testreflection.Wolf");
if (f != null) {
f.eat();
}
}
}

打印结果为

1
2
dog eat shit
wolf eat meat

参考

Java
Java初级码农博客