Java反射机制
关键词:
Introspection(内省、内观)
Reflection(反射)
##反射机制是java的高级技巧,世界上著名的框架struts,hibernate,spring的实现,无不用到了反射机制,反射机制可以让代码灵活,从而实现可配置化。
##Reflection
这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods1。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
##Class
Class class十分特殊。它和一般classes一样继承自Object,其,实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class object。如果您想借由“修改Java标准库源码”来观察Class object的实际生成时机(例如在Class的constructor内添加一个println()),不能够!因为Class并没有public constructor.
Class是Reflection故事起源。针对任何您想探勘的class,唯有先为它产生一个Class object,接下来才能经由后者唤起为数十多个的Reflection APIs。这些APIs将在稍后的探险活动中一一亮相。
##"Class” object的取得途径
Java允许我们从多种管道为一个class生成对应的Class object
1.getClass(),每个class 都有此函数
示例 String str = "abc";
Class c1 = str.getClass();
2.Class.getSuperclass()
示例 Button b = new Button();
Class c1 = b.getClass();
Class c2 = c1.getSuperclass();
3.运用static method Class.forName()(最常被使用)
示例 Class c1 = Class.forName ("java.lang.String");
Class c2 = Class.forName ("java.awt.Button");
Class c3 = Class.forName ("java.util.LinkedList$Entry");
Class c4 = Class.forName ("I");
Class c5 = Class.forName ("[I");
4.运用.class 语法
示例 Class c1 = String.class;
Class c2 = java.awt.Button.class;
Class c3 = Main.InnerClass.class;
Class c4 = int.class;
Class c5 = int[].class;
5.运用primitive wrapper classes的TYPE 语法
Class c1 = Boolean.TYPE;
Class c2 = Byte.TYPE;
Class c3 = Character.TYPE;
Class c4 = Short.TYPE;
Class c5 = Integer.TYPE;
Class c6 = Long.TYPE;
Class c7 = Float.TYPE;
Class c8 = Double.TYPE;
Class c9 = Void.TYPE;
##Java Reflection API 运用示例
Class c = Class.forName("");
c.getPackage();//得到Package
c.getDeclaredFields//得到类的所有字段
c.getDeclaredConstructors();//得到类的所有构造函数
c.getDeclaredMethods();();//得到类的所有方法
。。。其他不详细描述,查询java api即可
##
找出class参用(导入)的所有classes
没有直接可用的Reflection API可以为我们找出某个class参用的所有其它classes。要获得这项信息,必须做苦工,一步一脚印逐一记录。我们必须观察所有fields的类型、所有methods(包括constructors)的参数类型和回返类型,剔除重复,留下唯一。这正是为什么图5-2程序代码要为tName()指定一个hashtable(而非一个null)做为第二自变量的缘故:hashtable可为我们储存元素(本例为字符串),又保证不重复。
本文讨论至此,几乎可以还原一个class的原貌(唯有methods 和ctors的定义无法取得)。接下来讨论Reflection 的另三个动态性质:(1) 运行时生成instances,(2) 执
行期唤起methods,(3) 运行时改动fields。
运行时生成instances
欲生成对象实体,在Reflection 动态机制中有两种作法,一个针对“无自变量ctor”,
一个针对“带参数ctor”。图6是面对“无自变量ctor”的例子。如果欲调用的是“带参数ctor“就比较麻烦些,图7是个例子,其中不再调用Class的newInstance(),而是调用Constructor 的newInstance()。图7首先准备一个Class[]做为ctor的参数类型(本例指定为一个double和一个int),然后以此为自变量调用getConstructor(),获得一个专属ctor。接下来再准备一个Object[] 做为ctor实参值(本例指定3.14159和125),调用上述专属ctor的newInstance()。
#001 Class c = Class.forName("DynTest");
#002 Object obj = null;
#003 obj = c.newInstance(); //不带自变量
#004 System.out.println(obj);
图6:动态生成“Class object 所对应之class”的对象实体;无自变量。
#001 Class c = Class.forName("DynTest");
#002 Class[] pTypes = new Class[] { double.class, int.class };
#003 Constructor ctor = c.getConstructor(pTypes);
#004 //指定parameter list,便可获得特定之ctor
#005
#006 Object obj = null;
#007 Object[] arg = new Object[] {3.14159, 125}; //自变量
#008 obj = ctor.newInstance(arg);
#009 System.out.println(obj);
图7:动态生成“Class object 对应之class”的对象实体;自变量以Object[]表示。
运行时调用methods
这个动作和上述调用“带参数之ctor”相当类似。首先准备一个Class[]做为ctor的参数类型(本例指定其中一个是String,另一个是Hashtable),然后以此为自变量调用getMethod(),获得特定的Method object。接下来准备一个Object[]放置自变量,然后调用上述所得之特定Method object的invoke(),如图8。知道为什么索取Method object时不需指定回返类型吗?因为method overloading机制要求signature(署名式)必须唯一,而回返类型并非signature的一个成份。换句话说,只要指定了method名称和参数列,就一定指出了一个独一无二的method。
#001 public String func(String s, Hashtable ht)
#002 {
#003 …System.out.println("func invoked"); return s;
#004 }
#005 public static void main(String args[])
#006 {
#007 Class c = Class.forName("Test");
#008 Class ptypes[] = new Class[2];
#009 ptypes[0] = Class.forName("java.lang.String");
#010 ptypes[1] = Class.forName("java.util.Hashtable");
#011 Method m = c.getMethod("func",ptypes);
#012 Test obj = new Test();
#013 Object args[] = new Object[2];
#014 arg[0] = new String("Hello,world");
#015 arg[1] = null;
#016 Object r = m.invoke(obj, arg);
#017 Integer rval = (String)r;
#018 System.out.println(rval);
#019 }
图8:动态唤起method
运行时变更fields内容
与先前两个动作相比,“变更field内容”轻松多了,因为它不需要参数和自变量。首先调用Class的getField()并指定field名称。获得特定的Field object之后便可直接调用Field的get()和set(),如图9。
#001 public class Test {
#002 public double d;
#003
#004 public static void main(String args[])
#005 {
#006 Class c = Class.forName("Test");
#007 Field f = c.getField("d"); //指定field 名称
#008 Test obj = new Test();
#009 System.out.println("d= " + (Double)f.get(obj));
#010 f.set(obj, 12.34);
#011 System.out.println("d= " + obj.d);
#012 }
#013 }
分享到:
相关推荐
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取和操作任何已知名称的类的内部信息。这一机制使得Java具备了一定的动态性,虽然在传统的分类中Java被视为静态类型语言。通过反射,开发者可以在...
侯捷先生是一位著名的Java技术专家,他的"流星絮语"系列教程深入浅出地讲解了Java反射机制。通过他的学习笔记,我们可以更深入地理解如何在实际项目中应用反射,解决一些特定问题,如插件化开发、序列化、动态代理等...
Java作为一门广泛使用的编程语言,其高级编程内容涵盖了众多领域,包括但不限于面向...侯捷的《java反射机制》.pdf是一个很好的起点,它将引导你深入理解Java反射的奥秘,而其他高级主题的学习则需要不断实践和探索。
8. **反射与动态代理**:Java的反射机制能让我们在运行时检查类的信息并操作对象,动态代理则能在运行时创建具有特定接口的代理类,这对于AOP(面向切面编程)和插件式系统很有用。 9. **Java EE基础**:虽然不是...
这本书经过侯捷的翻译,确保了内容的准确性和可读性,对于中文读者来说,是学习和提升Java技能的理想资源。 在Java的世界里,实践是掌握编程技巧的关键。本书深入探讨了Java语言的核心特性,包括语法、面向对象编程...
本课程的教学目标是使学生掌握 Java 的基础知识,掌握 JDK 开发环境和系统配置,能够使用面向对象思想进行程序设计,掌握图形用户界面的设计方法,掌握 Applet 技术,掌握异常处理技术,了解线程机制、IO 流、网络...
7. **反射与注解**:反射机制允许程序在运行时检查类、接口和对象的信息,而注解为代码提供了元数据,增强了代码的可读性和自解释性。书中将涵盖这两个高级主题的使用。 8. **Java SE与Java EE**:区分Java标准版...
《Practical Java》和《Effective Java》正是这样两部著作,它们对Java的重要而基础的技术细节进行了详尽、深刻的介绍和剖析,每个主题独立成章,既方便读者根据需求选择性阅读,又能彼此呼应,形成一个完整的学习...
《Practical Java》是由著名程序员侯捷编写的关于Java编程实践的一部著作,该书深入浅出地探讨了Java编程的各个方面,旨在帮助开发者提升实际编程能力。在压缩包"practical_java.zip"中,包含了两个主要文件:...
《Word排版艺术》是侯捷先生所著的一本详细介绍Microsoft Word排版技巧和艺术的书籍。侯捷作为台湾著名的电脑图书作家,在电脑软件领域有着深厚的造诣,尤其是对Word软件的深入理解和运用经验。这本书主要面向那些...
"Java制作一个图形编辑系统(课题论文及代码)" 以下是从给定的文件中生成的知识点: ... 该系统的参考文献包括丁振凡的《Java语言实用教程》、侯捷的《Thinking in Java 2e中文版》、李尊朝的《Java语言程序设计》等。
博览网视频 侯捷c++新特性 STL源码分析 陈硕网络编程 c++设计模式等等
《侯捷-java编程思想》这份文档很可能提供了深入的Java编程理念,包括面向对象设计原则、设计模式、异常处理、多线程以及集合框架等。侯捷作为知名的编程教育专家,他的著作往往能帮助读者理解并运用Java语言的精髓...
《C++ Templates全覽》是一本由侯捷等译自David Vandevoorde与Nicolai M. Josuttis所著的《C++Templates—The Complete Guide》的专业书籍。该书作为C++模板编程的权威指南,覆盖了模板的基础概念、语言细节、设计...
- 本书被认为是最完整的Java教程之一,涵盖了从基础概念到高级技术的各个方面。 - 内容安排遵循逻辑顺序,确保读者能够逐步掌握知识,并深入理解每个主题。 2. **示例与实践**: - 提供了大量的实例代码,帮助...