Java-反射机制详解
Posted Frank_Lei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java-反射机制详解相关的知识,希望对你有一定的参考价值。
本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看理论的话,看了也不懂,不过建议大家在看完文章之后,在回过头去看看理论,会有更好的理解。
下面开始正文。
【案例1】通过一个对象获得完整的包名和类名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
package Reflect; /** * 通过一个对象获得完整的包名和类名 * */ class Demo{ //other codes... } class hello{ public static void main(String[] args) { Demo demo= new Demo(); System.out.println(demo.getClass().getName()); } } |
【运行结果】:Reflect.Demo
添加一句:所有类的对象其实都是Class的实例。
【案例2】实例化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
|
package Reflect; class Demo{ //other codes... } class hello{ public static void main(String[] args) { Class<?> demo1= null ; Class<?> demo2= null ; Class<?> demo3= null ; try { //一般尽量采用这种形式 demo1=Class.forName( "Reflect.Demo" ); } catch (Exception e){ e.printStackTrace(); } demo2= new Demo().getClass(); demo3=Demo. class ; System.out.println( "类名称 " +demo1.getName()); System.out.println( "类名称 " +demo2.getName()); System.out.println( "类名称 " +demo3.getName()); } } |
【运行结果】:
类名称 Reflect.Demo
类名称 Reflect.Demo
类名称 Reflect.Demo
【案例3】通过Class实例化其他类的对象
通过public无参构造实例化对象(私有化无参构造函数会抛出InstantiationException异常)
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
|
package Reflect; class Person{ public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public String toString(){ return "[" + this .name+ " " + this .age+ "]" ; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Person per= null ; try { per=(Person)demo.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } per.setName( "Rollen" ); per.setAge( 20 ); System.out.println(per); } } |
【运行结果】:
[Rollen 20]
但是注意一下,当我们把Person中的默认的无参构造函数取消的时候,比如自己定义只定义一个有参数的构造函数之后,会出现错误:
比如我定义了一个构造函数:
1
2
3
4
|
public Person(String name, int age) { this .age=age; this .name=name; } |
然后继续运行上面的程序,会出现:
java.lang.InstantiationException: Reflect.Person
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at Reflect.hello.main(hello.java:39)
Exception in thread "main" java.lang.NullPointerException
at Reflect.hello.main(hello.java:47)
所以大家以后再编写使用Class实例化其他类的对象的时候,一定要自己定义无参的构造函数
【案例】通过Class调用其他类中的构造函数 (也可以通过这种方式通过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
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
|
package Reflect; import java.lang.reflect.Constructor; class Person{ public Person() { } public Person(String name){ this .name=name; } public Person( int age){ this .age=age; } public Person(String name, int age) { this .age=age; this .name=name; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString(){ return "[" + this .name+ " " + this .age+ "]" ; } private String name; private int age; } class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Person per1= null ; Person per2= null ; Person per3= null ; Person per4= null ; //取得全部的构造函数 Constructor<?> cons[]=demo.getConstructors(); try { per1=(Person)cons[ 0 ].newInstance(); per2=(Person)cons[ 1 ].newInstance( "Rollen" ); per3=(Person)cons[ 2 ].newInstance( 20 ); per4=(Person)cons[ 3 ].newInstance( "Rollen" , 20 ); } catch (Exception e){ e.printStackTrace(); } System.out.println(per1); System.out.println(per2); System.out.println(per3); System.out.println(per4); } } |
【运行结果】:
[null 0]
[Rollen 0]
[null 20]
[Rollen 20]
getConstructors():
返回一个包含某些 Constructor
对象的数组,这些对象反映此 Class
对象所表示的类的所有公共构造方法。如果该类没有公共构造方法,或者该类是一个数组类,或者该类反映一个基本类型或 void,则返回一个长度为 0 的数组。 注意,此方法返回 Constructor<T>
对象的数组(即取自此类构造方法的数组)时,此方法的返回类型是 Constructor<?>[]
,不是 预期的 Constructor<T>[]
。此少量信息的返回类型是必需的,因为从此方法返回之后,该数组可能被修改以保存不同类的 Constructor
对象,而这将违反 Constructor<T>[]
的类型保证。
返回:表示此类公共构造方法的 Constructor
对象数组
抛出:SecurityException
- 如果存在安全管理器 s,并满足下列任一条件:
- 调用
s.checkMemberAccess(this, Member.PUBLIC)
拒绝访问该类中的构造方法 - 调用者的类加载器不同于也不是当前类的类加载器的一个祖先,并且对
s.checkPackageAccess()
的调用拒绝访问该类的包
【案例】
返回一个类实现的接口:
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
|
package Reflect; interface China{ public static final String name= "Rollen" ; public static int age= 20 ; public void sayChina(); public void sayHello(String name, int age); } class Person implements China{ public Person() { } public Person(String sex){ this .sex=sex; } public String getSex() { return sex; } public void setSex(String sex) { this .sex = sex; } @Override public void sayChina(){ System.out.println( "hello ,china" ); } @Override public void sayHello(String name, int age){ System.out.println(name+ " " +age); } private String sex; } class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } //保存所有的接口 Class<?> intes[]=demo.getInterfaces(); for ( int i = 0 ; i < intes.length; i++) { System.out.println( "实现的接口 " +intes[i].getName()); } } } |
【运行结果】:
实现的接口 Reflect.China
getInterfaces():
确定此对象所表示的类或接口,所实现的接口。
如果此对象表示一个类,则返回值是一个数组,它包含了表示该类所实现的所有接口的对象。数组中接口对象顺序与此对象所表示的类的声明的 implements
子句中接口名顺序一致。例如,给定声明:
class Shimmer implements FloorWax, DessertTopping { ... }
设 s
的值为 Shimmer
的一个实例;表达式:
s.getClass().getInterfaces()[0]
的值为表示 FloorWax
接口的 Class
对象;
s.getClass().getInterfaces()[1]
的值为表示 DessertTopping
接口的 Class
对象。
如果此对象表示一个接口,则该数组包含表示该接口扩展的所有接口的对象。数组中接口对象顺序与此对象所表示的接口的声明的 extends
子句中接口名顺序一致。
如果此对象表示一个不实现任何接口的类或接口,则此方法返回一个长度为 0 的数组。
如果此对象表示一个基本类型或 void,则此方法返回一个长度为 0 的数组。
- 返回:
- 该类所实现的接口的一个数组。
(注意,以下几个例子,都会用到这个例子的Person类,所以为节省篇幅,此处不再粘贴Person的代码部分,只粘贴主类hello的代码)
【案例】:取得其他类中的父类
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } //取得父类 Class<?> temp=demo.getSuperclass(); System.out.println( "继承的父类为: " +temp.getName()); } } |
【运行结果】
继承的父类为: java.lang.Object
【案例】:获得其他类中的全部构造函数
这个例子需要在程序开头添加import java.lang.reflect.*;
然后将主类编写为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class hello{ public static void main(String[] args) { Class<?> demo= null ; try { demo=Class.forName( "Reflect.Person" ); } catch (Exception e) { e.printStackTrace(); } Constructor<?>cons[]=demo.getConstructors(); for ( int i = 0 ; i < cons.length; i++) { System.out.println( "构造方法: " +cons[i]); } } } |
【运行结果】:
构造方法: public Reflect.Person()
构造方法: public Reflect.Person(java.lang.String)
但是细心的读者会发现,上面的构造函数没有public 或者private这一类的修饰符
下面这个例子我们就来获取修饰符
1
2
3
4
5
6
7
8
9
10
11
12
以上是关于Java-反射机制详解的主要内容,如果未能解决你的问题,请参考以下文章
|