You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 39 Next »

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]] "8.4.8.2 Hiding (by Class Methods)".

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

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 attempts to override a static method but fails to understand that he has actually hidden the static method. Consequently, his code unexpectedly invokes the displayAccountStatus() method of the 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.

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

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.

class GrantAccess {
  public void displayAccountStatus() {
    System.out.print("Account details for admin: XX");
  }
}

class GrantUserAccess extends GrantAccess {
  @Override  
  public 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");	
  }
}

Note that "In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass methods—they are new methods, unique to the subclass." [[Tutorials 2008]].

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]]. Consequently, there may be no hiding when the methods have different return types or throws clauses.

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.

  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

Automated 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

[[Bloch 2005]] Puzzle 48: All I Get Is Static
[[JLS 2005]] "8.4.8.2 Hiding (by Class Methods)"
[[Tutorials 2008]] Overriding and Hiding Methods


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

  • No labels