运行时类型信息使得你可以在程序运行时发现和使用类型信息。
本章将讨论 Java 是如何允许我们在运行期识别对象和类的信息。主要有两种方式:一种是传统的RTTI,它假定我们在编译期和运行期已经知道了所有的类型;另一种是“反射机制(reflection)”,它允许我们在运行期获得类的信息。我们先讨论“传统”的RTTI,再讨论反射。
使用RTTI,你可以查询某个Shape引用所指向的对象的确切类型,然后选择或者剔除特例。
Class
要理解RTTI在Java中是如何工作的,首先必须要知道类型信息在运行期是如何表示的。这项工作是由被称为“Class对象”的特殊对象完成的,它包含了与类有关的信息。事实上,Class对象正是被用来创建类的“常规”对象的。
作为程序一部分,每个类都有一个Class对象。换言之,每当你编写并且编译了一个新类,就会产生一个Class对象(更恰当地说,是被保存在一个同名的.class文件中)
因此,Java程序在它开始运行之前并非被完全加载,其各个部分是在必须时才加载的。
一旦某个类的Class对象被载入内存,它就被用来创建这个类的所有对象。
Class对象仅在需要的时候才被加载,static初始化是在类加载时进行的。
forName()是取得Class对象的引用的一种方法。它是用一个包含目标类的文本名(注意拼写和大小写)的String作输入参数,返回的是一个Class对象的引用,上面的代码忽略了返回值。
对forName()的调用是为了它产生的“副作用”:如果类Gum还没有被加载就加载它。在加载的过程中,Gum的static语句被执行。
如果你已经拥有了一个感兴趣的类型的对象,那就可以通过调用getClass()方法来获取Class引用了,这个方法属于根类Object的一部分,它将返回表示该对象的实际类型的Class引用。Class包含很多有用的方法,下面就是其中的一部分:
package typeinfo.toys;
interface HasBatteries {}
interface Waterproof {}
interface Shoots {}
class Toy {
Toy() {}
Toy(int i) {}
}
class FancyToy extends Toy implements HasBatteries, Waterproof, Shoots{
FancyToy() {
super(1);
}
}
public class ToyTest {
static void printInfo(Class cc) {
System.out.println("Class nameL " + cc.getName() +
"is interface: [" + cc.isInterface() + "]");
System.out.println("Sample name: " + cc.getSimpleName());
System.out.println("Canonical name: " + cc.getCanonicalName());
}
public static void main(String[] args) {
Class c = null;
try {
c = Class.forName("typeinfo.toys.FancyToy");
} catch (ClassNotFoundException e) {
System.out.println("cant find FancyToy");
System.exit(1);
}
printInfo(c);
for(Class face : c.getInterfaces()) {
printInfo(face);
}
Class up = c.getSuperclass();
Object obj = null;
try {
obj = up.newInstance();
} catch (InstantiationException e) {
System.out.println("cannt instantiate");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.out.println("cannt access");
e.printStackTrace();
}
printInfo(obj.getClass());
}
}
Output:
Class nameL typeinfo.toys.FancyToyis interface: [false]
Sample name: FancyToy
Canonical name: typeinfo.toys.FancyToy
Class nameL typeinfo.toys.HasBatteriesis interface: [true]
Sample name: HasBatteries
Canonical name: typeinfo.toys.HasBatteries
Class nameL typeinfo.toys.Waterproofis interface: [true]
Sample name: Waterproof
Canonical name: typeinfo.toys.Waterproof
Class nameL typeinfo.toys.Shootsis interface: [true]
Sample name: Shoots
Canonical name: typeinfo.toys.Shoots
Class nameL typeinfo.toys.Toyis interface: [false]
Sample name: Toy
Canonical name: typeinfo.toys.Toy
在传递给forName的字符串中,你必须使用全限定名。在main中Class.getInterfaces()方法返回的是Class对象,它们表示在感兴趣的Class对象中所包含的接口。getSuperClass也一样。
Class的newInstance()方法是实现“虚拟构造器”的一种途径,虚拟构造器允许你声明:“我不知道你的确切类型,但是无论如何要正确地创建你自己。”在前面的示例中,up仅仅只是一个Class引用,在编译期不具备任何更进一步的类型信息。当你创建新实例时,会得到Object引用,但是这个引用指向的是Toy对象。另外,使用newInstance()来创建的类,必须带有默认的构造器。
分享到:
相关推荐
第14 章无线应用协议 第15 章实例研究1 ─数据双重性 第16 章实例研究2 —X M L 和分布式应用程序 第17 章实例研究3 —图书目录信息服务 第18 章实例研究4 —SOAP 附录A XML 1.0 规范 附录B IE 5 XML ...
第14 章无线应用协议 第15 章实例研究1 ─数据双重性 第16 章实例研究2 —X M L 和分布式应用程序 第17 章实例研究3 —图书目录信息服务 第18 章实例研究4 —SOAP 附录A XML 1.0 规范 附录B IE 5 XML ...
XML 高级编程_分章节上传(18-26)最后一部分 1.XML 简介 2.第2章XML 语法 3.第3章文档类型定义 ...14.第14章无线应用协议 16.第15章实例研究1─数据双重性 。。。。。。。。。。。。。。。。。。。。。。
14. **会话、用户和注册(第十四章)** 讲解了Django如何处理用户的会话状态,以及如何实现用户认证和注册功能。 15. **缓存机制(第十五章)** 分析了Django的缓存机制及其应用场景,帮助开发者提高应用性能。...
太大了,只能分章节传上来啊。。看过1-5章的就知道质量么样了啊。。。需要的继续下(6-9)哦。...14.第14章无线应用协议 16.第15章实例研究1─数据双重性 。。。。。。。。。。。。。。。。。。。。。
XML 高级编程_分章节下载(1-5),好不好,自己看了就知道哦。。不好后面的就不需要下载了啊,好的话就...14.第14章无线应用协议 16.第15章实例研究1─数据双重性 。。。。。。。。。。。。。。。。。。。。。。。。。
#### 第14章 通用串行总线全速接口(USB2.0FS) USB接口支持高速数据传输,可用于与PC或其他USB设备进行通信。 #### 第15章 控制器局域网络(bxCAN) bxCAN模块实现了CAN协议,适用于汽车工业和其他领域中的实时...
这个课程特别关注第四章的课后习题答案,这表明它可能涵盖了Android应用程序开发的关键概念和实践。 Android是Google开发的一款开源操作系统,主要用于移动设备,如智能手机和平板电脑。学习Android程序设计,...
第四章涉及流程控制的高级结构: 1. **Case-Switch**: 用于基于不同情况执行不同代码的结构。 2. **Default**: switch语句中未匹配到case时执行的代码块。 3. **Exit**: 结束程序或方法。 4. **Exception**: 异常...
14. CSS美化网页 CSS可以用于美化网页,设置网页的布局、颜色、字体等样式。 本资源是HTML+CSS教学课件,涵盖了HTML的基本结构、HTML5的发展史、W3C标准、网页编辑工具、HTML基本结构、网页基本信息、标题标签、...
### Zabbix教程从入门到精通知识点总结 #### 第一章:简介 - **Zabbix介绍** ...#### 第十一章:事件确认 - **事件确认(Event confirmation)** - 需要管理员手动确认报警事件,避免重复报警。
6. 转换和格式化:`round()` 函数用于四舍五入,例如 `round(3.1415926,2)` 返回3.14,`round(3.1415926)` 返回3。`format()` 方法用于格式化输出字符串,可以控制对齐、填充字符等,例如输出星号围绕的数字。 7. ...
第14章是核心章节,将本书介绍的许多主题串联在一起。我们已经选择了高级渲染技术的一个样本,并展示了实现这些功能的示例。该章包含使用法线贴图的逐像素照明、环境贴图、粒子系统、图像后处理、程序纹理、阴影...
第14章 大型交换式网络上的路由 193 14.1 问题 194 14.2 OSPF扩展 197 14.2.1 Opaque LSA 197 14.2.2 地址解析通告 198 14.3 PNNI扩展 200 14.3.1 PNNI扩充选路 200 14.3.2 代理PAR 202 14.3.3 综合的PNNI 204 更多...