您的位置:首页 > 编程语言 > Java开发

Java核心技术第5章(7)

2015-10-13 10:11 281 查看

5.7 反射

    反射(reflection library)提供了非常丰富的工具集,以便编写能够动态操纵Java代码的程序.这项功能被大量地应用于JavaBeans中,它是Java组件的体系结构.使用反射,Java可以支持Visual Basic用户习惯使用的工具,特别是在设计或运行中添加新类时,能够快速地应用开发工具动态地查询新添加类的能力.

    能够分析类能力的程序称为反射,反射机制可以用来:

    在运行中分析类的能力

    在运行中查看对象,例如,编写一个toString类方法供所有类使用

    实现通用的数组操纵代码

    利用Method对象,这个对象很像C++中的函数指针

5.7.1   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
    如果e是经理,则会打印出
Manager Harry
    获取Class类对象的第二种方法是调用静态方法forName:
String className = "java.util.Date";
Class cl = Class.forName(className);
    获取Class类对象的第三种方法非常简单,如果T是任意的Java类型,T.class将代表匹配的类对象,例如:
Class cl1 = Date.class;
Class cl2 = int.class;
Class cl3 = Double[].class;
    一个Class对象实际上表示的是一个类型.

    虚拟机为每个类型管理一个Class对象,因此,可以利用==运算符实现两个类对象比较的操作.例如,
if (e.getClass() == Employee.class) ...
    还有一个很有用的方法newInstance(),可以用来快速地创建一个类的实例.例如
e.getClass().newInstance();
    创建了一个与e具有相同类型的实例.newInstance方法调用默认的构造器(没有参数的构造器)初始化新创建的对象.

    将forName与newInstance配合起来使用,可以根据存储在字符创中的类名创建一个对象.
String s = "java.util.Date";
Object m = Class.forName(s).newInstance();
    注释:newInstance方法对应C++虚拟构造器的习惯用法.然而,C++的虚拟构造器不是一种语法特性.需要由专门的库支持,Class类与C++中的 type_info类相似,getClass方法与C++中的 typeid 运算符等价.但Java中的Class比C++中的type_info功能强.C++中的type_info只能以字符串的形式显示一个类型的名字,而不能创建那个类型的对象.

5.7.2   捕获异常

    当程序运行过程中发生错误时,就会"抛出异常".抛出异常比终止程序要灵活得多,这是因为可以提供一个"捕获"异常的处理器对异常情况进行处理.

    如果没有提供处理器,程序就会终止,并在控制台上打印出一条信息,其中给出了异常的类型.

    异常有两种类型:未检查异常和已检查异常,对于已检查异常,编译器将会检查是否提供了处理器.然而,还有很多常见的异常,例如,访问 null 引用,都属于未检查异常,编译器不会查看是否为这些错误提供了处理器.

    Class.forName方法就是一个抛出已检查异常的例子.将可能抛出已检查异常的一个或多个方法调用代码放在 try 块中,然后在 catch 子句中提供处理器代码.
try
{
statement that might throw exceptions
}
catch (Exception e)
{
handler action
}
    下面是一个示例:
try
{
String name = ...;  // get Class name
Class cl = Class.forName(name);     // might throw exception
do something with cl
}
catch (Exception e)
{
e.printStackTrace();
}
    java.lang.Class方法如下所示:
static Class forName(String className);
    返回描述类名为className的Class对象
Object newInstance();
    返回这个类的一个新实例

5.7.3   利用反射分析类的能力

    在java.lang.reflect包中有三个类Field,Method,Constructor分别用于描述类的域,方法和构造器.这三个类都有一个叫做getName的方法,用来返回项目的名称.Field类有一个getType方法,用来返回描述域所属类型的Class对象.Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回返回类型的方法.这三个类还有一个叫做getModifiers的方法,它将返回一个整型数值,用不同的位开关描述
public 和 static 这样的修饰符使用状况.

    Class类的getFields,getMethods,getConstrution方法将返回类提供的 public 域,方法和构造器数组.

5.7.4   在运行时使用反射分析对象

5.7.5   使用反射编写泛型数组代码

5.7.6   调用任意方法

5.8 继承设计的技巧

    下面给出一些对设计继承关系很有帮助的建议.

    1.将公共操作和域放在超类

    2.不要使用受保护的域


    3.使用继承实现"is-a"关系

    4.除非所有继承的方法都有意义,否则不要使用继承

    5.在覆盖方法时,不要改变预期的行为
    6.使用多态,而非类型信息

    7.不要过多地使用反射
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: