低效的空字符串测试¶
ID: java/inefficient-empty-string-test
Kind: problem
Security severity:
Severity: recommendation
Precision: high
Tags:
- efficiency
- maintainability
Query suites:
- java-security-and-quality.qls
当检查字符串 s
是否为空时,最明显的解决方案可能是编写类似 s.equals("")
(或 "".equals(s)
)的内容。但是,这实际上会带来相当大的开销,因为 String.equals
在开始比较字符串内容之前会执行一些类型测试和转换。
建议¶
检查字符串 s
是否为空的首选方法是检查其长度是否等于零。因此,条件是 s.length() == 0
。 length
方法作为简单的字段访问实现,因此应该比调用 equals
快得多。
请注意,在 Java 6 及更高版本中,String
类具有 isEmpty
方法,用于检查字符串是否为空。如果代码库不需要支持 Java 5,则最好使用该方法。
示例¶
在以下示例中,类 InefficientDBClient
使用 equals
来测试字符串 user
和 pw
是否为空。请注意,测试 "".equals(pw)
可以防止 NullPointerException
,但如果 user
为 null
,则测试 user.equals("")
会抛出 NullPointerException
。
相比之下,类 EfficientDBClient
使用 length
而不是 equals
。该类通过保护 pw.length() == 0
而不是 user.length() == 0
并通过明确测试 null
来保留 InefficientDBClient
的行为。是否需要此保护取决于程序的预期行为。
// Inefficient version
class InefficientDBClient {
public void connect(String user, String pw) {
if (user.equals("") || "".equals(pw))
throw new RuntimeException();
...
}
}
// More efficient version
class EfficientDBClient {
public void connect(String user, String pw) {
if (user.length() == 0 || (pw != null && pw.length() == 0))
throw new RuntimeException();
...
}
}
参考¶
Java API 规范:String.length()、String.isEmpty()、String.equals()。