Wiki Markup |
---|
When a class declares a static method _m_, the declaration of _m_ hides any method _m'_, where the signature of _m_ is a subsignature of the signature of _m'_ and the declaration of _m'_ is both in the superclasses and superinterfaces of the declaring class and also would otherwise be accessible to code in the declaring class \[[JLS 2005|AA. Bibliography#JLS 05]\] ["8.4.8.2 Hiding (by Class Methods)"|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.8.2]. |
Programmers may confuse hiding with overriding. An instance method defined in a subclass overrides another instance method in the superclass when
- Both have the same name
- Number and type of parameters is same
- Return type is same
The Hiding term is used in context of a class method (or field) that has the same signature as the corresponding class method (or field) in the superclass or superinterface.
The difference between these two is that the overridden method gets invoked from the subclass while the hidden method may get invoked from either the superclass or the subclass, depending on how it is invoked (name qualification).
Noncompliant Code Example
To differentiate between overriding and hiding, a common nomenclature is used. The method to be invoked is decided at either compile time (if the base method is static
, as in this noncompliant code example) according to the type of the qualifier or at run time otherwise (for non-static methods). A qualifier is a part of the invocation expression before the dot (for example, the variables admin
and user
in this noncompliant code example).
Hiding and overriding differ in the determination of which method is invoked from a call site. For overriding, the method invoked is determined at runtime based on the specific object instance in hand. For hiding, the method invoked is determined at compile time based on the specific qualified name or method invocation expression used at the call site.
Noncompliant Code Example
In this noncompliant example, the programmer This noncompliant example attempts to override a static
method but fails to consider it as a hiding case. As a result understand that he has actually hidden the static method. Consequently, his code unexpectedly invokes the displayAccountStatus()
method of the superclass is invoked on both the calls. Moreover, expressions that are normally used for dynamic dispatch while overriding have been used even though achieving this is impossible with static
methodsthe superclass at two different call sites, rather than invoking the superclass method at one call site and the subclass method at the other. Additionally, his code uses expressions that are typical of dynamic dispatch, further indicating his confusion.
Code Block | ||
---|---|---|
| ||
class GrantAccess { public static void displayAccountStatus() { System.out.print("Account details for admin: XX"); } } class GrantUserAccess extends GrantAccess { public static void displayAccountStatus() { System.out.print("Account details for user: XX"); } } public class StatMethod { public static void choose(String username) { GrantAccess admin = new GrantAccess(); GrantAccess user = new GrantUserAccess(); if(username.equals("admin")) { admin.displayAccountStatus(); } else { user.displayAccountStatus(); } } public static void main(String[] args) { choose("user"); } } |
Compliant Solution
This compliant solution correctly classifies this case as hiding and uses absolute, fully qualified class names GrantAccess
and GrantUserAccess
to clearly state the intent. Refrain from qualifying a static
method invocation with an expression meant for dynamic dispatch.In this compliant solution, the programmer declares the displayAccountStatus()
methods as instance methods, by removing the static keyword. Consequently, the dynamic dispatch at the call sites produces the expected result. He also uses the @Override
annotation to indicate intentional overriding of the parent method.
Code Block | ||
---|---|---|
| ||
class GrantAccess { public static void displayAccountStatus() { System.out.print("Account details for admin: XX"); } } class GrantUserAccess extends GrantAccess { @Override public static void displayAccountStatus() { System.out.print("Account details for user: XX"); } } public class StatMethod { public static void choose(String username) { GrantAccess admin = new GrantAccess(); GrantAccess user = new GrantUserAccess(); if(username.equals("admin")) { GrantAccessadmin.displayAccountStatus(); } else { GrantUserAccessuser.displayAccountStatus(); } } public static void main(String[] args) { choose("user"); } } |
...
Wiki Markup |
---|
Technically, a {{private}} method cannot be hidden or overridden. There is no requirement that {{private}} methods with the same signature in the subclass and the superclass, bear any relationship in terms of having the same return type or {{throws}} clause, the necessary conditions for _hiding_ \[[JLS 2005|AA. Bibliography#JLS 05]\]. Consequently, there may be no _hiding_ when the methods have different return types or {{throws}} clauses. |
@Override
annotation be used to clearly specify that a method is the overridden version and not the hidden one.Exceptions
MET11-EX1: Method hiding may occasionally be unavoidable. Declaration of hiding methods is permissible in such cases, provided that all invocations of hiding or hidden methods use qualified names or method invocation expressions that explicitly indicate which specific method will be invoked. If the example above had been such a case, modification of the choose
method as shown below would have been an acceptable alternative.
Code Block | ||
---|---|---|
| ||
public static void choose(String username) {
if(username.equals("admin")) {
GrantAccess.displayAccountStatus();
} else {
GrantUserAccess.displayAccountStatus();
}
}
|
Risk Assessment
Confusing overriding and hiding can produce unexpected results.
Guideline | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
MET11-J | low | unlikely | medium | P2 | L3 |
Automated Detection
TODOAutomated detection of violations of this guideline appear to be straightforward. Automated determination of cases where method hiding was unavoidable appears to be infeasible. However, determining whether all invocations of hiding or hidden methods explicitly indicate which specific method will be invoked appears to be straightforward.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
Wiki Markup |
---|
\[[Tutorials 2008|AA. Bibliography#Tutorials 08]\] [Overriding and Hiding Methods|http://java.sun.com/docs/books/tutorial/java/IandI/override.html] \[[Bloch 2005|AA. Bibliography#Bloch 05]\] Puzzle 48: All I Get Is Static \[[JLS 2005|AA. Bibliography#JLS 05]\] ["8.4.8.2 Hiding (by Class Methods)"|http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.6.3 Requirements in .8.2] \[[Tutorials 2008|AA. Bibliography#Tutorials 08]\] [Overriding and Hiding Methods|http://java.sun.com/docs/books/tutorial/java/IandI/override.html] |
...
MET10-J. For methods that return an array or collection prefer returning an empty array or collection over a null value 05. Methods (MET) MET12-J. Ensure objects that are equated are equatable