The Java Language Specification

class RawMembers<T> extends NonGeneric implements Collection<String> { static Collection<NonGeneric> cng = new ArrayList<NonGeneric>(); public static void main(String[] args) { RawMembers rw = null; Collection<Number> cn = rw.myNumbers(); // OK Iterator<String> is = rw.iterator(); // Unchecked warning Collection<NonGeneric> cnn = rw.cng; // OK, static member } } In this program (which is not meant to be run), RawMembers<T> inherits the method: Iterator<String> iterator() from the Collection<String> superinterface. The raw type RawMembers inherits iterator() from Collection, the erasure of Collection<String>, which means that the return type of iterator() in RawMembers is Iterator. As a result, the attempt to 4.9 Intersection Types TYPES, VALUES, AND VARIABLES 70 assign rw.iterator() to Iterator<String> requires an unchecked conversion, so a compile-time unchecked warning is issued. In contrast, RawMembers inherits myNumbers() from the NonGeneric class whose erasure is also NonGeneric. Thus, the return type of myNumbers() in RawMembers is not erased, and the attempt to assign rw.myNumbers() to Collection<Number> requires no unchecked conversion, so no compile-time unchecked warning is issued. Similarly, the static member cng retains its parameterized type even when accessed through a object of raw type. Note that access to a static member through an instance is considered bad style and is discouraged. This example reveals that certain members of a raw type are not erased, namely static members whose types are parameterized, and members inherited from a non-generic supertype. Raw types are closely related to wildcards. Both are based on existential types. Raw types can be thought of as wildcards whose type rules are deliberately unsound, to accommodate interaction with legacy code. Historically, raw types preceded wildcards; they were first introduced in GJ, and described in the paper Making the future safe for the past: Adding Genericity to the Java Programming Language by Gilad Bracha, Martin Odersky, David Stoutamire, and Philip Wadler, in Proceedings of the ACM Conference on Object-Oriented Programming, Systems, Languages and Applications (OOPSLA 98), October 1998. 4.9 Intersection Types An intersection type takes the form T1 & ... & Tn (n > 0), where Ti (1 ≤ i ≤ n) are types. Intersection types can be derived from type parameter bounds (§4.4) and cast expressions (§15.16); they also arise in the processes of capture conversion (§5.1.10) and least upper bound computation (§4.10.4). The values of an intersection type are those objects that are values of all of the types Ti for 1 ≤ i ≤ n. Every intersection type T1 & ... & Tn induces a notional class or interface for the purpose of identifying the members of the intersection type, as follows: • For each Ti (1 ≤ i ≤ n), let Ci be the most specific class or array type such that Ti <: Ci. Then there must be some Ck such that Ck <: Ci for any i (1 ≤ i ≤ n), or a compile-time error occurs. • For 1 ≤ j ≤ n, if Tj is a type variable, then let Tj' be an interface whose members are the same as the public members of Tj; otherwise, if Tj is an interface, then let Tj' be Tj. TYPES, VALUES, AND VARIABLES Subtyping 4.10 71 • If Ck is Object, a notional interface is induced; otherwise, a notional class is induced with direct superclass Ck. This class or interface has direct superinterfaces T1', ..., Tn' and is declared in the package in which the intersection type appears. The members of an intersection type are the members of the class or interface it induces. It is worth dwelling upon the distinction between intersection types and the bounds of type variables. Every type variable bound induces an intersection type. This intersection type is often trivial, consisting of a single type. The form of a bound is restricted (only the first element may be a class or type variable, and only one type variable may appear in the bound) to preclude certain awkward situations coming into existence. However, capture conversion can lead to the creation of type variables whose bounds are more general, such as array types).