JDK-6910491 : Hiding of non-generic static method by generic static method
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 7
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2009-12-15
  • Updated: 2024-04-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.7.0-ea"
Java(TM) SE Runtime Environment (build 1.7.0-ea-b77)
Java HotSpot(TM) Client VM (build 17.0-b05, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
If you create a base class with a static method, and then create a subclass with a generic static method that has the same name, the compiler fails. It thinks that the two methods have the same erasure but neither overrides the other; this doesn't make any sense because a static method can't override another static method. It also reports that a reference to that method is ambiguous, even when the method reference is qualified with an explicit class name.
Note that the problem only occurs when the static method in the subclass is generic. If you remove the generic type parameter from the sample code included below then it compiles correctly.
This appears to be a regression defect as it worked with javac 1.6.0_17 (it also works with the Eclipse 3.5.1 internal java compiler).

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the sample code with javac build 1.7.0-ea-b77.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected the compilation to succeed.
ACTUAL -
The compilation failed with the error message shown below.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
J:\>javac.exe Test.java
Test.java:8: name clash: <T>foo() in Sub and foo() in Base have the same erasure, yet neither overrides the other
    static <T> void foo() {
                    ^
  where T is a type-variable:
    T extends Object declared in method <T>foo()
Test.java:16: reference to foo is ambiguous, both method foo() in Base and method <T>foo() in Sub match
        Sub.<Object>foo();
           ^
  where T is a type-variable:
    T extends Object declared in method <T>foo()
2 errors

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
class Base {
    static void foo() {
	System.out.println("Base");
    }
}

class Sub extends Base {
    static <T> void foo() {
	System.out.println("Sub");
    }
}

public class Test {
    public static void main(final String[] args) {
	Base.foo();
	Sub.<Object>foo();
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Change the name of one of the static methods.

Release Regression From : 6u17
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
The spec changes being contemplated (changes to "subsignature", if I am reading correctly) may overlap or duplicate the discussion in JDK-7023317.
31-07-2014

EVALUATION This is only matter of fixing diagnostic.
31-08-2010

EVALUATION Morally, a generic static method in a subclass hides a non-generic static method with the same name and signature in the superclass. Technically, as per 8.4.8.2, the subclass method must be a subsignature of the superclass method. Sub.foo and Base.foo do _not_ have the same number of type parameters, so Sub.foo is not deemed a subsignature of Base.foo (8.4.2), so Sub.foo is not deemed to hide Base.foo (8.4.8.2). javac is technically correct. (Sidebar: if the requirement on type parameters was reworked, then the requirement for subsignatures would still prevent this reasonable-looking hiding, because foo(T<:String) in Sub is not the same as foo(String) in Base, nor is foo(T<:String) in Sub the same as the erasure of foo(String) in Base. clase Base { static void foo(String s) {..} } class Sub extends Base { static <T extends String> void foo(T s) {..} } ) However, javac's error is rather off-base. As noted by the submitter, no overriding is being attempted, only hiding. 8.4.8.3 should say "m1 or some method m1 overrides ***or hides*** ... has the same erasure as m2 or sme method m2 overrides ***or hides*** ...". The hiding is still illegal without a change to 8.4.2, which is not proposed here.
21-08-2010

EVALUATION This problem has been introduced by 5009937. Should a generic static method hide a non-generic static method with same name and signature? Looking at 8.4.8.3 it seems like javac is correct here. Reassigning to spec for further evaluation.
19-08-2010