Do not reuse the names of publicly visible identifiers, public utility classes, interfaces, or packages in the Java Standard Library.
When a developer uses an identifier that has the same name as a public class, such as {{Vector}}, a subsequent maintainer might be unaware that this identifier does not actually refer to {{java.util.Vector}} and might unintentionally use the custom {{Vector}} rather than the original {{java.util.Vector}} class. The custom type {{Vector}} can [shadow|BB. Definitions#shadow] a class name from {{java.util.Vector}}, as specified by the JLS, [§6.3.2, "Obscured Declarations"|http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.3.2] \[[JLS 2005|AA. Bibliography#JLS 05]\]. This can result in unexpected program behavior. |
Well-defined import statements can resolve these issues. However, when reused name definitions are imported from other packages, use of the _type-import-on-demand declaration_ (see the JLS, [§7.5.2, "Type-Import-on-Demand Declaration"|http://java.sun.com/docs/books/jls/third_edition/html/packages.html#7.5.2] \[[JLS 2005|AA. Bibliography#JLS 05]\]) can complicate a programmer's attempt to determine which specific definition was intended to be used. Additionally, a common practice that can lead to errors is to produce the import statements _after_ writing the code, often via automatic inclusion of import statements by an IDE. This creates further ambiguity with respect to the names. When a custom type is found earlier than the intended type in the Java include path, no further searches are conducted. Consequently, the wrong type is silently adopted. |
This noncompliant code example implements a class that reuses the name of the class java.util.Vector. It attempts to introduce a different condition for the isEmpty() method for interfacing with native legacy code by overriding the corresponding method in java.util.Vector. Unexpected behavior can arise if a maintainer confuses the isEmpty() method with the java.util.Vector.isEmpty() method.
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");
}
}
}
|
This compliant solution uses a different name for the class, preventing any potential shadowing of the class from the Java Standard Library.
class MyVector {
//other code
}
|
When the developer and organization control the original shadowed class, it may be preferable to change the design strategy of the original in accordance with Bloch's _Effective Java_ \[[Bloch 2008|AA. Bibliography#Bloch 08]\], Item 16, _Prefer interfaces to abstract classes_. Changing the original class into an interface would permit class {{MyVector}} to declare that it implements the hypothetical {{Vector}} interface. This would permit client code that intended to use {{MyVector}} to remain compatible with code that uses the original implementation of {{Vector}}. |
Public identifier reuse decreases the readability and maintainability of code.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
|---|---|---|---|---|---|
DCL01-J |
low |
unlikely |
medium |
P2 |
L3 |
An automated tool can easily detect reuse of the set of names representing public classes or interfaces from the Java Standard Library.
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="fbd01833-da45-42dc-a142-b368d4e8243c"><ac:plain-text-body><![CDATA[ |
[[JLS 2005 |
AA. Bibliography#JLS 05]] |
[§6.3.2, Obscured Declarations |
http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.3.2] |
]]></ac:plain-text-body></ac:structured-macro> |
|
|||||
|
|||||
|
|||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="29522359-2e44-4331-b8ed-e104415f4a1d"><ac:plain-text-body><![CDATA[ |
[[FindBugs 2008 |
AA. Bibliography#FindBugs 08]] |
]]></ac:plain-text-body></ac:structured-macro> |
||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="ed279234-8944-414f-8a9c-d692f13c4508"><ac:plain-text-body><![CDATA[ |
[[Bloch 2005 |
AA. Bibliography#Bloch 05]] |
Puzzle 67, All strung out |
]]></ac:plain-text-body></ac:structured-macro> |
|
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="6830c3a8-d8b9-494f-ab1b-df328c4f3b0f"><ac:plain-text-body><![CDATA[ |
[[Bloch 2008 |
AA. Bibliography#Bloch 08]] |
Item 16, Prefer interfaces to abstract classes |
]]></ac:plain-text-body></ac:structured-macro> |
01. Declarations and Initialization (DCL) DCL02-J. Declare all enhanced for statement loop variables final