JDK-5094290 : Inaccurate warning for a return value from an incomplete parameterized class
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-08-30
  • Updated: 2004-11-23
  • Resolved: 2004-11-23
Related Reports
Duplicate :  
Description

Name: jl125535			Date: 08/30/2004


FULL PRODUCT VERSION :
java version "1.5.0-beta3"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-beta3-b60)
Java HotSpot(TM) Client VM (build 1.5.0-beta3-b60, mixed mode, sharing)

A DESCRIPTION OF THE PROBLEM :
Javac gets carried away by unused/irrelevant type parameters and starts giving false alarms on concretely-typed _inherited_ members.
In this sample both Bug$A and Bug$B inherit from Vector<String>. So it's a compile-time FACT that  the invocation of the method #elements() yields an enumeration of Strings in both cases. So the parameterisation of Bug$B should have no influence on the outcome of that operation.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the sample code provided with "-Xlint:unchecked" on.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All 3 assignments to Enumeration<String> are type sound so the javac mustn't emit any warnings.
ACTUAL -
  Bug.java:8: warning: [unchecked] unchecked conversion
found   : java.util.Enumeration
required: java.util.Enumeration<java.lang.String>
                Enumeration<String> e2 = new B().elements(); // Unchecked conversion?!

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.*;

public class Bug {

	public static void main(String[] args){
		Enumeration<String> e1 = new A().elements();

		Enumeration<String> e2 = new B().elements(); // Unchecked conversion?!
		Enumeration<String> e3 = new B<Thread>().elements();
	}

	static class A extends Vector<String> {}

	static class B <X> extends Vector<String> {}
}
---------- END SOURCE ----------
(Incident Review ID: 301336) 
======================================================================

Comments
EVALUATION This is a "raw type" which is part of the language to preserve backwards compatibility. It is not unsafe to instantiate a raw type, but to convert it to a parameterized type. That is what the warning says. ###@###.### 2004-08-30 Some quotes from JLS (��4.8): "To facilitate interfacing with non-generic legacy code, it is also possible to use as a type the erasure (��4.6) of a parameterized type (��4.5). ... The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of genericity into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types. ... The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized instances." In particular this means that the direct supertype of the raw type Bar.B is the raw type Vector, not Vector<String>. Also, don't ever use raw types. Raw types are in the language to facilitate backwards compatibility. The mechanism is surprisingly complex and we would end up breaking some old programs if the specification were changed to not include the super type. If you ever want to solve a problem by mixing raw with generics: don't. It should always be possible to use unbounded wildcards <?> instead. Otherwise, file a bug and let us know. ###@###.### 2004-09-01
01-09-2004