------- 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 }
运行结果:
时间: 2024-10-19 00:36:02