5.5 Java编程的安全性

有些编程语言被称为类型安全语言,但程序员使用这个术语时要表达的意思却很宽松。“类型安全”有很多解读和定义方式,而且各种方式之间并不都有关联。对我们要讨论的话题来说,类型安全最适合理解为编程语言的一个属性,其作用是避免运行时把数据识别为错误的类型。类型安全与否是相对的,正确的理解方式应该是,一门语言比(或没有)另一门语言安全,而不能直接断定一门语言是绝对安全的或绝对不安全的。

Java 的类型系统是静态的,能避免很多问题,例如,如果程序员试图把不兼容的值赋值给变量,会导致编译出错。但是,Java 的类型安全并不完美,因为任何两种引用类型之间都可以通过校正相互转换——如果值之间不兼容,这种转换在运行时会失败,抛出 ClassCastException 异常。

本书所说的安全性和更宽泛的正确性分不开,也就是说,我们要站在程序的角度,而不是语言的角度来探讨安全性。这强调了一个问题,即代码的安全不是由任何一门广泛使用的语言决定的,而要由程序员付出足够的努力(并严格遵守编程准则),确保写出的代码真正安全且正确。

为了得到安全的程序,我们要使用图 5-1 表示的抽象状态模型。安全的程序具有以下特征:

  • 所有对象在创建后都处于一种合法状态;

  • 外部可访问的方法在合法状态之间转换对象;

  • 外部可访问的方法绝对不能返回状态不一致的对象;

  • 弃用对象之前,外部可访问的方法必须把对象还原为合法状态。

{%}

图 5-1:程序的状态转换

其中,“外部可访问”的方法是指声明为 publicprotected 或者对包私有的方法。上述特征为安全的程序定义了一个合理的模型,而且按照这种方式定义的抽象类型,它的方法能保证状态的一致性。满足上述条件的程序就可以称为“安全的程序”,而不用管程序使用何种语言实现。

5.5 Java编程的安全性 - 图2 私有方法不用保证对象在使用前后都处于合法状态,因为私有方法不能在外部代码中调用。

你可能想到了,如果想在大量代码中让状态模型和方法都满足上述特征,需要付出相当多的精力。对 Java 等语言来说,因为程序员能直接创建由多个线程执行的抢占式多任务程序,所以要付出的精力更多。

介绍完 Java 的面向对象设计要略之后,关于 Java 语言和平台还有一个方面需要扎实地理解——内存管理和并发编程。这是 Java 平台最复杂的知识,但掌握之后会获益良多。这是下一章要讨论的话题,介绍完之后本书第一部分也就结束了。