反射
来源:互联网 发布:破解压缩文件密码软件 编辑:程序博客网 时间:2024/05/23 20:56
------- android培训、java培训、期待与您交流! ----------
一、反射概念
- 反射就是把Java类中的各种成分映射成相应的Java类。
- 例如,一个Java类中用一个Class类的对象来表示,
- 一个类中的组成部分:成员变量,方法,构造方法,包等信息也用一个个Java类来表示。
- 就像汽车是一个类,其中的发动机,变速箱等等也是一个类。
- 表示Java类的Class类显然要提供一系列的方法,来获取其中的变量,方法,构造方法,修饰符,包等信息。这些信息就是用相应类的实例对象来表示,他们是Field、Method、Contructor、Package等等。
- 一个类中的每一个成员都可以用相应的反射API类的一个实例对象来表示,通过调用Class类的方法可以得到这些实例对象后,得到这些实例对象有什么用?怎么用?这正是学习和应用反射的要点。
- 理解:
- Java的类进入内存,变成一份份Java字节码文件,每一份字节码文件就是Class类的实例对象(因为Class类就是描述这些字节码文件的类,是所有字节码文件的类)。
- 字节码文件就是把所有类的字节码文件抽取出的共性(属性、方法、各种信息)封装为一个统一的Class类,而每个字节码文件就是这个Class类的一个实例对象,所以这些对象可以调用Class类的方法,如getMehod(),isPrimitive(),getConstructor()等等。
- 反射把这些组成部分封装起来
- 组成部分的字节码文件: Field、Method、Contructor、Package等,这些字节码文件是Class类的实例对象,这些实例对象提供了一些方法暴露自己的信息。
- 疑问?
- 这些字节码文件与要反射的类有什么关系呢?
- 比如说String.class.getConstructor();这一句是String的字节码字节码文件(Class类的实例对象)使用了 Contructor字节码文件 (Class类的实例对象)的 getConstructor()方法?
- 牢记:
- 字节码文件是对象,是Class类的实例对象。
- 得到Class的三种方法:
01.String str1 = "abc"; 02.//得到Class的三种方法:对象.getClass,类.class,Class.forName("类名") 03.Class cls1 = str1.getClass(); 04.Class cls2 = String.class; 05.Class cls3 = Class.forName("java.lang.String");
三、Field的反射
01.ReflectPoint pt1 = new ReflectPoint(3,5); 02.//通过字节码,得到Field类对象 03.Field fieldY = pt1.getClass().getField("y"); 04.System.out.println(fieldY.get(pt1));// 05. 06.//得到private的字段 07.Field fieldX = pt1.getClass().getDeclaredField("x");//private�����ɼ� 08.fieldX.setAccessible(true); 09.System.out.println(fieldY.get(pt1));
四、Method的反射
01.Method methodCharAt = String.class.getMethod("charAt", int.class); 02.System.out.println(methodCharAt.invoke(str1,1)); 03.System.out.println(methodCharAt.invoke(str1, new Object[]{2}));//JDK1.4
五、用反射调用其他类的main 方法。
01.//用反射调用其他的main方法 02.String startingClassName = args[0]; 03.Method mainMethod = Class.forName(startingClassName).getMethod("main", String[].class); 04.mainMethod.invoke(null, new Object []{new String[]{"111","222","333"}}); 05.mainMethod.invoke(null, (Object)new String[] {"111","222","333"});
六、数组与Object及其反射类型
- 如果参数是Object的之类,那么按照JDK1.4可以打印出元素。
- 如果参数是基本数据类型,那么按照JDK1.5的传递一个可变参数,只打印数组的[I@65656。对于这段话,疑问··~
private static void printObject(Object obj) { Class<? extends Object> clazz = obj.getClass(); if (clazz.isArray()) { int len = Array.getLength(obj); for (int i = 0; i < len; i++) { System.out.println(Array.get(obj, i)); } } else System.out.println(obj); }
七、反射的作用-举例
例子来源:http://www.cnblogs.com/zxl-jay/archive/2011/09/25/2190585.html
需求:设计一个主板,为了提高后期的扩展性,也就是为了后期提高电脑的额功能,对外提供了PCI的接口。以方便电脑功能的扩展。
interface PCI{ void open(); void close(); } class MainBoard{ public void usePCI(PCI p){ p.open(); p.close(); } } class MainBoardDemo{ public static void main(String[] args){ MainBoard mb=new MainBoard(); //mb.usePCI(null); mb.usePCI(NetCard); } }
后期,要进行电脑功能的扩展,需加入一个网卡,只需要定义一个网卡类实现PCI接口,只要覆盖这个规则,主板就可以使用该板卡
class NetCard implements PCI{ public void open();{ system.out.println("open"); } public void close();{ system.out.println("close"); } }那么为了使用其网卡,还需要做一个步骤就是在已定义好的应用程序中,建立网卡对象,并作为参数传入,那么就是对原有的程序进行修改。这样不利于程序的健壮性。
可不可以在不修改源码的基础上运行后期出现的这些子类对象呢?
只要在前期设计时,将后期指定的类进行对象的建立,这样后期的子类对象就不需要再建立对象,只要将子类名称告知即可。
为了获取后期对象,并在前期可以使用,或对外提供了一个配置文件。前期程序可以直接操作该配置文件,后期的子类只需要将子类名称存入配置文件即可。
这时就需要动态的获取指定的类并预先创建对象
就用到了反射机制。重新修改一下应用程序。 class MainBoardDemo{ public static void main(String[] args){ MainBoard mb=new MainBoard(); File file=new File("conf.txt"); BufferenReader buff = new BufferenReader(new FileReader(file)); String className = buff.readLine(); Class clazz = Class.forName(className); PCI p = (PCI)clazz.newInstance(); mb.usePCI(p); } }
配置文件conf.txt
当后期出现网卡或者声卡的时候,只需要将该子类的全类名存入配置文件即可, 源程序不需要进行修改
在该例中,可以了解,反射给我们的程序带来了很强的扩展性。
八、反射的作用-框架的概念
- 比如在反射中,调用一个未知类的main(),未知类是后来的。这个反射就实现了一个小框架。
- 框架是提前做好的,框架调用用户的类,就像房子是框架,新门是用户类。
- 反射做的框架有个好处:将来的类可以调用以前的类。框架不需要知道将来的类叫什么。
------- android培训、java培训、期待与您交流! ----------