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的字段 ,只限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

 

posted @ 2016-02-29 16:01  npe0  阅读(429)  评论(2编辑  收藏  举报