反射
反射库(reflection library)提供了一态操纵Java代码的程序。 这项功能被大量地应用于JavaBeans中, 它是Java组件的体系结构,使用反射Java可以支持Visual Basic用户习惯使用的工具。 特别是在设计或运行中添加新类时能够快速地应用开发工具动态地查询新添加类的能力。能够分析类能力的程序称为反射(reflective)。 反射机制的功能极其强大。
反射机制可以用来:
- 在运行时分析类的能力。
- 在运行时查看对象,
- 实现通用的数组操作代码
- 利用Method对象, 这个对象很像C++中的函数指针。
Class类
Class类在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。 这个信息跟踪着每个对象所属的类。 虚拟机利用运行时类型信息选择相应的方法执行。
然而, 可以通过专门的Java类访问这些信息。 保存这些信息的类被称为Class, 这个名字很容易让人混淆。 Object类中的getClass()方法将会返回一个Class类型的实例。
Employee e;
Class cl=e.getClass();
如同用 个 Employee 对象表示 个特定的雇员属性 一样,一个Class 对象将表示 个特 定类的属性。 最常用的 Class 方法是 getName。这个方法将返回类的名字。
System.out.println(e.getClass().getName()+e.getName());
如果e是一个雇员,则会打印
Employee Harry Hacker
如果e是一个经理,则会打印
Manager Harry Hacker
如果类在一个包里, 包的名字也作为类名的一部分
Random generator = new Random() ;
Class cl = generator.getClass();
String name= cl .getName(); //name is set to "java.util .Random"
还可以调用静态方法 forName 获得类名对应的 Class 对象。
String className = "java.util .Random";
Cl ass c 1 = Cl ass. forName(c 1 ass Name);
如果类名保存在字符串中, 并可在运行中改变, 就可以使用这个方法。 当然, 这个方法只有在 className 是类名或接口名时才能够执行。 否则, forName 方法将抛出一个checkedexception (已检查异常) 。 无论何时使用这个方法, 都应该提供个异常处理器 (exceptionhandler)。
提示:在启动时, 包含 main 方法的类被加栽。 它会加载所有需要的类。 这些被加载的类又要加栽它们需要的类, 以此类推。 对于个大型的应用程序来说, 这将会消耗很多时,可以给用户启动速度比较快的幻觉不过, 要确保包含 main 方法的类没有显式地引用其他的类。 首先, 显示一个启动画面然后, 通过调用 Class.forName 手工地加栽其他的类。
一个Class对象实际上表示的是一个类型,而这个类型未必一定是一种类。
Class 类实际上是一 个泛型类。 例如, Employee.class 的类型是 Class。没有说明这个问题的原因是: 它将已经抽象的概念更加复杂化了。 在大多数实际问题中, 可以忽略类型参数, 而使用原始的 Class 类。虚拟机为每个类型管理一个 Class 对象。 因此 , 可以利用=运笋符实现两个类对象比较 的操作。
newlnstance()可以用来动态地创建一个类的实例
e. getClass().newInstance();
创建了一个与 e 具有相同类类型的实例。 newInstance 方法叫用默认的构造盎(没有参数的构造器)初始化新创建的对象.如果这个类没有默认的构造器, 就会抛出一个异常。
将 forNan1e 与 newInstance 配合起来使用, 可以根据存储在字符串中的类名创建一个对象
String s = "java.util .Random";
Object m = Class. forName(s) .newlnstance();
如果需要以这种方式向希望按名称创建的类的构造器提供参数 , 就不要使用上面那条语句, 而必须使用 Constructor 类中的 newlnstance 方法。
newlnstance 方法对应 C++ 中虚拟构造器的习惯用法 然而, C++ 中的虚拟构造器不是一种语言特性, 需要由专门的库支持。 Class 类与 C++ 中的 type_info 类相似, getClass 方法与 C++ 中的 typeid 运算符等价,, 但 Java 中的 Class 比 C++中的 type_info 的功能强。 C++中的 type_info 只能以字符串的形式显示一个类型的名字 , 而不能创建那个类型的对象)