Java反射
1、何为反射? 简而言之: 加载类,并解剖出类的各个组成部分。根据java语言的这一特性,可将Java视为一种动态语言。更好的理解反射机制有助于我们深层次的理解spring框架。
2、Class类 代表了一个类的字节码。 在 java.lang包中可以找到。
加载字节码的方法:
1 Class.forName("全类名"); Class.forName("com.mysql.jdbc.Driver");
该方法的作用是,加载某个类的字节码到内存中,并使用class对象进行封装。
3、如何获取class对象?下面用Demos.java来举例
1 package org.reflect.test;
2
3 public class Demos implements Serializable {
4
5 public String demoName0;
6 public String demoName2;
7 public String demoName3;
8 private String demotype0;
9 private String demotype1;
10 private String demotype2;
11
12 public Demos(){}
13
14 //构造函数
15 public Demos(String name, String type) {
16
17 }
18
19 //私有方法
20 private void getDemoName0(){
21
22
23 }
24 private void setDemoName1(){
25
26
27 }
28 private void setDemoName2(){
29
30
31 }
32
33 //共有方法
34 public void getDemoType0(){
35
36
37 }
38 public void getDemoType1(){
39
40
41 }
42 public void getDemoType2(){
43
44
45 }
46
47 //测试方法
48 public void sayHello(String s){
49
50 System.out.println("Public Hello"+s);
51 }
52
53 //测试方法
54 private void sayPrivateHello(String s){
55
56 System.out.println("Private Hello"+s);
57 }
58
59 }
获取方式:
1 //获取class类方式1
2 Class clazz1=Class.forName("org.reflect.test.Demos");
3 //方式2
4 Class clazz2=Demos.class;
5 //方式3
6 Class clazz3=new Demos().getClass();
4、获取包名,全类名,类的修饰符,父类,接口名,构造方法
1 //获取包名包名
2 String package1=clazz1.getPackage().getName();
3 String package2=clazz2.getPackage().getName();
4
5 System.out.println("包名1 :"+package1+"---包名2 :"+package2);
6
7 //获取类全名
8 String name1=clazz1.getName();
9 String name2=clazz2.getName();
10 System.out.println("类名1 :"+name1+"---类名2 :"+name2);
11
12 //获取类的修饰符
13 int mod=clazz1.getModifiers();
14 System.out.println("该类的修饰符 :"+Modifier.toString(mod));
15
16 //获取该类的父类
17 Class supercla=clazz1.getSuperclass();
18 System.out.println("父类 :"+supercla);
19
20 //获得该类的接口
21 Class []interfaces=clazz1.getInterfaces();
22 for (Class i:interfaces) {
23 System.out.println("接口名 :" + i.getName());
24 }
25
26
27 //获取该类的构造方法
28 Constructor []con=clazz1.getConstructors();
29 for (Constructor c :con) {
30 System.out.println("构造函数名 :"+c.getName());
31 }
32
输出结果:
5、获取该类的字段的两种方法:
getFields();
getDeclaredFields();
1 //获取该类的字段 ,只限public修饰符修饰的
2 Field[]fils=clazz1.getFields();
3 for (Field f :fils) {
4 System.out.println("fieldsName :"+f.getName());
5 }
6 //获取该类的所有的字段,public, protected, default(package) access, and private fields
7 //不包括继承来的属性
8 Field []filss=clazz1.getDeclaredFields();
9 for (Field f :filss) {
10 System.out.println("DeclaredFields :"+f.getName());
11 }
说明:getFields();该方法只获取本类中public修饰的属性,
getDeclaredFileds();该方法获取该类中所有的属性,包括私有,但是不包括继承来的属性。
输出结果:
6、获取该类的方法的两种方法:
getMethods();
getDeclaredMethods();
1 //获取该类的特定的方法 public,包括父类的以及接口实现的
2 Method[]methods=clazz1.getMethods();
3 for(Method m:methods){
4 System.out.println("Methods :"+m.getName());
5 }
6
7 //获取所有的方法,public private 仅限当前类,不包括父类
8 Method []method3=clazz1.getDeclaredMethods();
9 for(Method m : method3){
10 System.out.println("DeclaredMethods :"+m.getName());
11 }
说明:getMethods();获取该类public修饰的方法,包括父类及接口实现的
getDeclaredMethods();只获取本类中的所有方法,包括private修饰的
输出结果:
7、通过反射调用Demos类中的方法
1 //获得该类的一个实例
2 Demos c=(Demos) clazz2.newInstance();
3 Method method=clazz2.getMethod("sayHello", String.class);
4 method.invoke(c, "World!!!");
5
6 //getDeclaredMethod能获取到所有定义的方法。setAccessible方法为true 则可以访问到私有的方法
7 Demos c2=(Demos) clazz1.newInstance();
8 Method method2=clazz1.getDeclaredMethod("sayPrivateHello", String.class);
9 method2.setAccessible(true);
10 method2.invoke(c2, "World!!!!");
说明:getMethod("arg0","arg1"); arg0代表方法的名称,arg1代表参数的类型。
getDeclaredMethod("arg2","arg3"); arg2,arg3的含义同getMethod方法。
输出结果:
这里有一个小插曲,都知道私有的方法只能供本类使用,属于本类私有,但是这里我们可以看到利用反射可以访问到Demos类中的私有方法,所以下次面试遇到private修饰的方法能被其他类调用吗?就可以说利用反射是可以的 0.0