且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《Java安全编码标准》一3.2 DCL01-J不要重用Java标准库的已经公开的标识

更新时间:2022-09-27 12:42:23

3.2 DCL01-J不要重用Java标准库的已经公开的标识

不要重用那些在Java标准库中已经使用过的公共的标识、公共的工具类、接口或者包。
当一个程序员使用和公开类相同的名字时,如Vector对后来的维护者来说,他可能不知道这个标识并不是指?java.util.Vector?,并且可能会无意地使用这个自定义的Vector类而不是原有的java.util.Vector类。使得这个自定义的?Vector会遮蔽java.util.Vector类,正如在JLS的6.3.2节中提到的那样。从而会导致不可预期的程序行为。
良好定义的import语句可以解决这个问题。然而,当重用的命名定义是从其他包中导入时,使用type-import-on-demand declaration(详细参见JLS的7.5.2节“Type-Import-on-Demand Declaration”[JLS 2005])会将程序员弄糊涂,因为他需要确定哪一个定义是想要的。另外,因为我们通常会使IDE来自动包括import语句,所以一种常见的操作是在编写代码后才生成这些import语句,但这种做法容易导致错误。在Java包含的import引用路径中,如果在预期的类出现之前出现了一个自定义的类,那么不会进一步搜索,这样就会毫无知觉地使用了错误的类。

3.2.1 不符合规则的代码示例(类名称)

这个不符合规则的代码实现了一个类,这个类重用了java.util.Vector 的名称。它在isEmpty()中使用了一个不同的条件判断,尝试通过重写java.util.Vector中对应的方法来达到与遗留代码接口的目的。如果维护者混淆了这个isEmpty()和java.util.Vector. isEmpty(),就会出现不可预知的行为。

class Vector {
??private int val = 1;

??public boolean isEmpty() {
????if (val == 1) {???// compares with 1 instead of 0
??????return true;
????} else {
??????return false;
????}
??}
??// other functionality is same as java.util.Vector
}

// import java.util.Vector; omitted
public class VectorUser {
??public static void main(String[] args) {
????Vector v = new Vector();
????if (v.isEmpty()) {
??????System.out.println("Vector is empty");
????}
??}
}

3.2.2 符合规则的方案(类名称)

这个符合规则的方案为这个类使用了不同的名字,防止这个类作为任何潜在的Java标准类库中的类名称的遮蔽情况出现。

class MyVector {
??// other code
}

当程序员和开发团队可以控制那些被模仿的原始类,更好的方法就是改变对它们的设计策略,这些策略可以根据Bloch的《Effective Java》[Bloch 2008]一书中第16条,更倾向于接口而不是抽象类的方法来实现。将原始类改变成接口,这可以让MyVector类得以通过声明它是我们假设的接口Vector?的实现。这可以让使用MyVector的代码与使用原始Vector实现的代码互相兼容。

3.2.3 风险评估

重用公有的标识会降低代码的可读性和可维护性。
《Java安全编码标准》一3.2 DCL01-J不要重用Java标准库的已经公开的标识

自动化检测 对于重用了Java标准类库中公共类和接口的名字的问题,它们可以被自动检测工具很容易地检测到。

3.2.4 相关规范

《Java安全编码标准》一3.2 DCL01-J不要重用Java标准库的已经公开的标识

3.2.5 参考书目

《Java安全编码标准》一3.2 DCL01-J不要重用Java标准库的已经公开的标识