码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员-学习日记(反射)

时间:2015-07-12 09:31:46      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:

  ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

一、概述

  JAVA反射机制是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象方法的功能称为java语言的反射机制。

    动态获取类中信息,就是java反射。可以理解为对类的解剖。

    如果想要对指定名称的字节码文件进行加载并获取其中的内容并调用,这时就使用到了此技术。

示例:获取字节码文件对象的3种方式

Person.java 

 1 package reflect;
 2 
 3 public class Person {
 4     private int age;
 5     private String name;
 6     
 7     public Person(int age,String name)
 8     {
 9         super();
10         this.age = age;
11         this.name = name;
12         System.out.println("Person param run..." + this.name + ":" + this.age);
13     }
14     public Person()
15     {
16         super();
17         System.out.println("person run");
18     }
19     
20      public void show(){
21          System.out.println(name + "...show run..." + age);
22  }
23 
24      private void privateMethod(){
25              System.out.println("method run");
26      }
27     
28      public void paramMethod(String str,int num){
29              System.out.println("paramMethod run..." + str + ":" + num);
30      }
31     
32      public static void staticMethod(){
33              System.out.println("static method run...");
34      }
35 }

1??、Object类中的getClass()方法。使用该方法必须明确要获取的具体的类,并创建对象。所以比较麻烦。

2??、任何数据类型都具备有一静态属性(.class)来获取其对应的Class对象。虽然相对上一种方式简单,但还是要明确用到类中的静态成员。

3??、只要通过给定的类的字符串名称就能获取该类字节码文件。

ReflectDemo.java

 1 package reflect;
 2 //import reflect.Person;
 3 
 4 public class ReflectDemo {
 5 
 6     public static void main(String[] args) throws ClassNotFoundException {
 7         
 8         getClassObject_3();
 9         
10         
11     }
12     
13     public static void getClassObject_1()
14     {
15         Person p = new Person();
16         Class cls = p.getClass();
17         
18         Person p1 = new Person();
19         Class cls1 = p1.getClass();
20         
21         System.out.println(cls==cls1);
22     }
23     
24     public static void getClassObject_2()
25     {
26         Class clazz = Person.class;
27         Class clazz1 = Person.class;
28         
29         System.out.println(clazz == clazz1);
30     }
31     
32     public static void getClassObject_3() throws ClassNotFoundException
33     {
34         String className = "reflect.Person";
35         Class clazz = Class.forName(className);
36         System.out.print(clazz);
37     }
38 }

如果指定 的类中没有空参数构造函数。或者要创建的类对象需要通过指定的构造函数进行初始化。此时就不能用到newInstance方法了。

得到这个类的所有构造函数:

Constructor[] constr = Class.forName("reflect.Person").getConstructors();

获取某一个构造函数:

Constructor constr = Person.class.getConstructor(String.class,int.class);

创建实例对象:

Person p = (Person)constr.newInstance(30,"小王");

要注意的是创建实例时newInstance方法中的参数列表必须与获取Constructor的方法getConstructor方法中的参数列表一致。

示例:获取Class中的构造函数

 1 package reflect;
 2 
 3 
 4 import java.lang.reflect.Constructor;
 5 import java.lang.reflect.InvocationTargetException;
 6 
 7 public class ReflectDemo {
 8 
 9     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
10         
11         createNewObject_1();
12         createNewObject_2();
13         
14     }
15     
16     public static void createNewObject_1() throws ClassNotFoundException, InstantiationException, IllegalAccessException
17     {
18         String classname = "reflect.Person";
19         Class cls = Class.forName(classname);
20         Object obj = cls.newInstance();
21     }
22     
23     public static void createNewObject_2() throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
24     {
25         /*
26          * 使用getConstructor(parameterTypes)方法来获取指定名称对应类所
        体现的对象的构造函数
27 */ 28 String classname = "reflect.Person"; 29 //找到该名称类文件、加载进内存,并产生Class对象 30 Class cls = Class.forName(classname); 31 //获取到指定的构造函数对象 32 Constructor contr = cls.getConstructor(int.class,String.class); 33 //通过该构造函数对象的newInstance方法进行对象的初始化 34 Object obj = contr.newInstance(29,"小王"); 35 } 36 }

技术分享

示例:获取类的字段

 1 package reflect;
 2 //import reflect.Person;
 3 import java.lang.reflect.Field;
 4 import java.lang.reflect.Constructor;
 5 import java.lang.reflect.Field;
 6 import java.lang.reflect.InvocationTargetException;
 7 
 8 public class ReflectDemo {
 9 
10     public static void main(String[] args) throws Exception {
11         
12         getFieldDemo();
13     }
14     public static void getFieldDemo() throws Exception
15     {
16         Class cls = Class.forName("reflect.Person");
17         //getDeclaredField可以都获取到公共字段或私有字段
18         Field field = cls.getDeclaredField("age");
19         //对私有字段的访问取消权限检查。
20         field.setAccessible(true);
21         
22         Object obj = cls.newInstance();
23         field.set(obj, 31);
24         Object o = field.get(obj);
25         System.out.println(field);
26     }
27 }

技术分享

 

示例:获取类中的方法

 1 package reflect;
 2 import java.lang.reflect.Field;
 3 import java.lang.reflect.Constructor;
 4 import java.lang.reflect.Method;
 5 import java.lang.reflect.InvocationTargetException;
 6 
 7 public class ReflectDemo {
 8 
 9     public static void main(String[] args) throws Exception {
10         
11         getMethodDemo_1();
12         System.out.println("---------------------------");
13         getMethodDemo_2();
14         System.out.println("---------------------------");
15         getMethodDemo_3();
16     }
17     
18     public static void getMethodDemo_1() throws ClassNotFoundException
19     {
20         Class cls = Class.forName("reflect.Person");
21         Method[] methods = cls.getMethods();
22         methods = cls.getDeclaredMethods();
23         for (Method mthd:methods)
24         {
25             System.out.println(mthd);
26         }
27     }
28     public static void getMethodDemo_2() throws Exception
29     {
30         Class cls = Class.forName("reflect.Person");
31         Method mt = cls.getMethod("show", null);
32         Object obj = cls.newInstance();
33         Constructor contr = cls.getConstructor(int.class,String.class);
34         obj = contr.newInstance(21,"小米");
35         mt.invoke(obj, null);
36     }
37     public static void getMethodDemo_3() throws Exception
38     {
39         Class cls = Class.forName("reflect.Person");
40         Method mt = cls.getMethod("paramMethod", String.class,int.class);
41         Object obj = cls.newInstance();
42         
43         Constructor constr = cls.getConstructor();
44         obj = constr.newInstance();
45         mt.invoke(obj, "小李",23);
46     }
47 }

技术分享

应用场景:

一个应用程序已经完成编写,无需额外的代码加入了。而后期遇出现了需要加入新的功能的情况。就如同计算机一样,使用后期用户会置换更好的键盘、硬盘等,所以计算机事先预留了usb接口,只要符合此接口规则的设备,计算机就可以通过加载驱动来完成使用。

一个方便的作法是,对外提供一个配置文件,让后期出现的子类直接将类名写入配置文件中即可。该应用程序直接读取配置文件的内容,并查找与给定名称相同的类文件。

 1 package reflect;
 2 
 3 import java.io.File;
 4 import java.io.FileInputStream;
 5 import java.sql.PseudoColumnUsage;
 6 import java.util.Properties;
 7 
 8 public class ReflectTest {
 9      public static void main(String[] args)  throws Exception
10      {
11          Computer cp = new Computer();
12          cp.run();
13          
14          //关联配置文件
15          FileInputStream fis = new FileInputStream(new File("USB.properties"));
16          //将配置文件信息缓存到集合中
17          Properties props = new Properties();
18          props.load(fis);
19          for (int i = 1; i < props.size(); i++) {
20             String className = props.getProperty("USB"+i);
21             Class cls = Class.forName(className);
22             USB usb = (USB)cls.newInstance();
23             cp.viaUSB(usb);
24         }
25          fis.close();
26      }
27 }
28 
29 interface USB{
30     void plug();
31     void unplug();
32 }
33 
34 class Computer{
35     public void run() {
36         System.out.println("Computer is running");
37     }
38     public void viaUSB(USB usb){
39         if(usb!=null){
40             usb.plug();
41             usb.unplug();
42         }
43     }
44 }
45 
46 class Keyboard implements USB{
47     @Override
48     public void plug() {
49         // TODO Auto-generated method stub
50         System.out.println("Keyboard plugged in!");
51     }
52 
53     @Override
54     public void unplug() {
55         // TODO Auto-generated method stub
56         System.out.println("Keyboard unplugged!");
57     }    
58 }
59 
60 class Monitor implements USB{
61 
62     @Override
63     public void plug() {
64         // TODO Auto-generated method stub
65         System.out.println("Monitor plugged in!");
66     }
67 
68     @Override
69     public void unplug() {
70         // TODO Auto-generated method stub
71         System.out.println("Monitor unplugged!");
72     }
73     
74 }

 

 

---恢复内容结束---

黑马程序员-学习日记(反射)

标签:

原文地址:http://www.cnblogs.com/tozr/p/4640493.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!