标签:
------- android培训、java培训、期待与您交流! ----------
黑马程序员------反射机制
1.1 反射机制
* JAVA反射机制是在运行状态中,对于任意一个类 (class文件),都能够知道这个类的所有属性和方法;
* 对于任意一个对象,都能够调用它的任意一个方法和属性;
* 这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
*
*
*反射其实就是动态加载一个指定的类,并获取该类中的所有的内容。
*而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员。
*就是把JAVA类中的各种成分反射成为相应的JAVA类
*简单说:反射技术可以理解为对一个类进行解剖。
1.2 反射机制原理图:
*
*
* 要想要对字节码文件进行解剖,必须要有字节码文件对象.
* 如何获取字节码文件对象呢?(示例1)
示例1:
1 public class ReflectDemo {
2 public static void main(String[] args) throws ClassNotFoundException {
3
4 getClassObject_1();
5
6 }
7 /*
8 * 只要通过给定的类的 字符串名称就可以获取该类,更为扩展。
9 * 可是用Class类中的方法完成。
10 * 该方法就是forName.
11 * 这种方式只要有名称即可,更为方便,扩展性更强。
12 */
13
14 public static void getClassObject_1() throws ClassNotFoundException {
15
16 String className = "cn.itcast.bean.Person";
17
18 Class clazz = Class.forName(className);
19
20 System.out.println(clazz);
21 }
22
23 }
1.3 反射的好处:大大的增强了程序的扩展性。
1.4 反射的基本步骤:
1、获得Class对象,就是获取到指定的名称的字节码文件对象。
2、实例化对象,获得类的属性、方法或构造函数。
3、访问属性、调用方法、调用构造函数创建对象。
得到类的字节码文件相同,这三种方式。
1.Class cls1=类名.class 相对简单,还是需要明确类名
2.cls1.getclass();必须要明确具体的类,并创建对象
3.class.forName("完整的类名(带包名)");
示例2:获取Class中的构造函数
1 package cn.itcast.reflect.demo;
2
3 import java.io.FileReader;
4 import java.lang.reflect.Constructor;
5
6 public class ReflectDemo2 {
7
8 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, Exception {
9
10 createNewObject_2();
11
12 }
13
14 public static void createNewObject_2() throws Exception {
15
16 /*
17 * 当获取指定名称对应类中的所体现的对象时,
18 * 而该对象初始化不使用空参数构造该怎么办呢?
19 * 既然是通过指定的构造 函数进行对象的初始化,
20 * 所以应该先获取到该构造函数。 通过字节码文件对象即可完成。
21 * 该方法是:getConstructor(paramterTypes);
22 *
23 */
24
25 String name = "cn.itcast.bean.Person";
26 //找寻该名称类文件,并加载进内存,并产生Class对象。
27 Class clazz = Class.forName(name);
28 //获取到了指定的构造函数对 象。
29 Constructor constructor = clazz.getConstructor(String.class,int.class);
30
31 //通过该构造器对象的newInstance方法进行对象的初始化。
32 Object obj = constructor.newInstance("小明",38);
33
34
35
36 }
37
38 public static void createNewObject() throws ClassNotFoundException, InstantiationException, IllegalAccessException{
39
40
41 //早期:new时候,先根据被new的类的名称找寻该类的字节码文件,并加载进内存,
42 // 并创建该字节码文件对象,并接着创建该字节文件的对应的Person对象.
43 // cn.itcast.bean.Person p = new cn.itcast.bean.Person();
44
45 //现在:
46 String name = "cn.itcast.bean.Person";
47 //找寻该名称类文件,并加载进内存,并产生Class对象。
48 Class clazz = Class.forName(name);
49 //如何产生该类的对象呢?
50 Object obj = clazz.newInstance();
51
52
53
54
55 }
56 }
示例3:获取Class的字段
1 package cn.itcast.reflect.demo;
2
3 import java.lang.reflect.Field;
4
5 public class ReflectDemo3 {
6
7 public static void main(String[] args) throws Exception {
8
9 getFieldDemo();
10
11 }
12
13 /*
14 * 获取字节码文件中的字段。
15 */
16 public static void getFieldDemo() throws Exception {
17
18 Class clazz = Class.forName("cn.itcast.bean.Person");
19
20 Field field = null;//clazz.getField("age");//只能获取公有的,
21
22 field = clazz.getDeclaredField("age");//只获取本类,但包含私有。
23
24 //对私有字段的访问取消权限检查。暴力访问。
25 field.setAccessible(true);
26
27 Object obj = clazz.newInstance();
28
29 //为对象的属性赋值
30 field.set(obj, 89);
31
32 //获取某对象的某属性值
33 Object o = field.get(obj);
34
35 System.out.println(o);
36
37 // cn.itcast.bean.Person p = new cn.itcast.bean.Person();
38 // p.age = 30;
39
40 }
41
42 }
43
示例4:获取Class中的方法
1 package cn.itcast.reflect.demo;
2
3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Method;
5
6 public class ReflectDemo4 {
7
8 public ReflectDemo4() {
9 }
10
11 public static void main(String[] args) throws Exception {
12
13 getMethodDemo_3();
14
15 }
16
17
18
19 public static void getMethodDemo_3() throws Exception {
20
21 Class clazz = Class.forName("cn.itcast.bean.Person");
22
23 Method method = clazz.getMethod("paramMethod", String.class,int.class);
24
25 Object obj = clazz.newInstance();
26
27 method.invoke(obj, "小强",89);
28
29
30 }
31
32 public static void getMethodDemo_2() throws Exception {
33
34 Class clazz = Class.forName("cn.itcast.bean.Person");
35
36 Method method = clazz.getMethod("show", null);//获取空参数一般方法。
37
38 // Object obj = clazz.newInstance();
39 Constructor constructor = clazz.getConstructor(String.class,int.class);
40 Object obj = constructor.newInstance("小明",37);
41
42
43 method.invoke(obj, null);
44
45
46
47 }
48
49 /*
50 * 获取指定Class中的所有公共函数。
51 */
52 public static void getMethodDemo() throws Exception {
53
54 Class clazz = Class.forName("cn.itcast.bean.Person");
55
56 Method[] methods = clazz.getMethods();//获取的都是公有的方法。
57 methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有。
58 for(Method method : methods){
59 System.out.println(method);
60 }
61
62
63 }
64
65 }
练习:反射练习
代码:
PCI.java
1 package cn.itcast.reflect.test;
2
3 public interface PCI
4 {
5 public void open();
6 public void close();
7 }
SoundCard.java
1 package cn.itcast.reflect.test;
2
3 public class SoundCard implements PCI
4 {
5 public void open(){
6 System.out.println("sound open");
7 }
8
9 public void close(){
10 System.out.println("sound close");
11 }
12 }
NetCard.java
1 package cn.itcast.reflect.test;
2
3 public class NetCard implements PCI
4 {
5 public void open(){
6 System.out.println("net open");
7 }
8
9 public void close(){
10 System.out.println("net close");
11 }
12 }
Mainboard.java
1 package cn.itcast.reflect.test;
2
3 public class Mainboard
4 {
5 public void run(){
6 System.out.println("main board run...");
7 }
8
9 public void usePCI(PCI p){
10 if(p != null){
11 p.open();
12 p.close();
13 }
14 }
15 }
pci.Properties
1 pci1=cn.itcast.reflect.test.SoundCard
2 pci2=cn.itcast.reflect.test.NetCard
ReflectTest.java
1 package cn.itcast.reflect.test;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5
6 import java.util.Properties;
7
8 /*
9 * 电脑运行
10 */
11 public class ReflectTest
12 {
13 public static void main(String[] args) throws Exception {
14
15 Mainboard mb = new Mainboard();
16
17 mb.run();
18 //每次添加一个设备都需要修改代码传递一个新创建的对象
19 //mb.usePCI(new SoundCard());
20 //能不能不修改代码就可以完成这个动作
21 //不用new完成,而是只获取其class文件,在内部实现创建对象的动作。
22
23 File configFile = new File("pci.properties");
24
25 Properties prop = new Properties();
26 FileInputStream fis = new FileInputStream(configFile);
27
28 prop.load(fis);
29
30 for(int x = 0; x < prop.size(); x++){
31
32 String pciName = prop.getProperty("pci" + (x + 1));
33
34 Class clazz = Class.forName(pciName);//用Class去加载这个pci子类
35
36 PCI p = (PCI)clazz.newInstance();
37
38 mb.usePCI(p);
39 }
40
41 fis.close();
42 }
43 }
运行结果:
标签:
原文地址:http://www.cnblogs.com/jiandonn/p/4581684.html