Angelika Langer - Training & Consulting
HOME | COURSES | TALKS | ARTICLES | GENERICS | LAMBDAS | IOSTREAMS | ABOUT | CONTACT | Twitter | Lanyrd | Linkedin
Books  
HOME 

GENERICS
  FAQ    
    CONTENT
    FUNDAMENTALS
    FEATURES
    PRACTICAL
    TECHNICAL
    INFORMATION
    GLOSSARY
    INDEX
    PDF VERSION
 
LAMBDAS 
IOSTREAMS 
ABOUT 
CONTACT 
Java Generics FAQs - Under The Hood Of The Compiler

This is a collection of answers to frequently asked questions (FAQs) about Java Generics, a new language feature added to the Java programming language in version 5.0 of the Java Standard Edition (J2SE 5.0).

If you want to provide feedback or have any questions regarding Java generics, to which you cannot find an answer in this document, feel free to send me EMAIL or use the GENERICS FAQ form.
A printable version of the FAQ documents is available in PDF format (4.5MB).

Java Generics FAQs - Under The Hood Of The Compiler

Technicalities - Under The Hood Of The Compiler

© Copyright 2003-2022 by Angelika Langer.  All Rights Reserved.
Compiler Messages Heap Pollution Type Erasure Type System Exception Handling Static Context Type Argument Inference Wilcard Capture Wildcard Instantiations Cast and instanceof Overloading and Overriding

Under The Hood Of The Compiler


 

Compiler Messages

What is an "unchecked" warning?

A warning by which the compiler indicates that it cannot ensure type safety.
The term "unchecked" warning is misleading.  It does not mean that the warning is unchecked in any way.  The term "unchecked" refers to the fact that the compiler and the runtime system do not have enough type information to perform all type checks that would be necessary to ensure type safety. In this sense, certain operations are "unchecked". 

The most common source of "unchecked" warnings is the use of raw types.  "unchecked" warnings are issued when an object is accessed through a raw type variable, because the raw type does not provide enough type information to perform all necessary type checks. 

Example (of unchecked warning in conjunction with raw types): 

TreeSet se t = new TreeSet();
set.add("abc");        // unchecked warning
set.remove("abc");


warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.TreeSet
               set.add("abc"); 
                      ^
When the add method is invoked the compiler does not know whether it is safe to add a String object to the collection.  If the TreeSet is a collection that contains String s (or a supertype thereof), then it would be safe.  But from the type information provided by the raw type TreeSet the compiler cannot tell.  Hence the call is potentially unsafe and an "unchecked" warning is issued. 
 

"unchecked" warnings are also reported when the compiler finds a cast whose target type is either a parameterized type or a type parameter. 

Example (of an unchecked warning in conjunction with a cast to a parameterized type or type variable): 

class Wrapper<T> {
  private T wrapped ;
  public Wrapper (T arg) {wrapped = arg;}
  ...
  p ublic Wrapper <T> clone() {
    Wrapper<T> clon = null;
     try { 
       clon = (Wrapper<T>) super.clone(); // unchecked warning
     } catch (CloneNotSupportedException e) { 
       throw new InternalError(); 
     }
     try { 
       Class<?> clzz = this.wrapped.getClass();
       Method   meth = clzz.getMethod("clone", new Class[0]);
       Object   dupl = meth.invoke(this.wrapped, new Object[0]);
       clon.wrapped = (T) dupl; // unchecked warning
     } catch (Exception e) {}
     return clon;
  }
}


warning: [unchecked] unchecked cast
found   : java.lang.Object
required: Wrapper <T>
                  clon = ( Wrapper <T>)super.clone(); 
                                                ^
warning: [unchecked] unchecked cast
found   : java.lang.Object
required: T
                  clon. wrapped = (T)dupl; 
                                    ^
A cast whose target type is either a (concrete or bounded wildcard) parameterized type or a type parameter is unsafe, if a dynamic type check at runtime is involved.  At runtime, only the type erasure is available, not the exact static type that is visible in the source code.  As a result, the runtime part of the cast is performed based on the type erasure, not on the exact static type. 

In the example, the cast to Wrapper<T> would check whether the object returned from super.clone is a Wrapper , not whether it is a wrapper with a particular type of members.  Similarly, the casts to the type parameter T are cast to type Object at runtime, and probably optimized away altogether.  Due to type erasure, the runtime system is unable to perform more useful type checks at runtime. 

In a way, the source code is misleading, because it suggests that a cast to the respective target type is performed, while in fact the dynamic part of the cast only checks against the type erasure of the target type.  The "unchecked" warning is issued to draw the programmer's attention to this mismatch between the static and dynamic aspect of the cast.

LINK TO THIS Technicalities.FAQ001
REFERENCES What does type-safety mean?
How can I disable or enable unchecked warnings?
What is the raw type?
Can I use a raw type like any other type?
Can I cast to a parameterized type?
Can I cast to the type that the type parameter stands for?

How can I disable or enable "unchecked" warnings?
 
Via the compiler options -Xlint:unchecked and -Xlint:-unchecked and via the standard annotation @SuppressWarnings("unchecked") .
The compiler option -Xlint:-unchecked disables all unchecked warnings that would occur in a compilation. 

The annotation @SuppressWarnings("unchecked") suppresses all warnings for the annotated part of the program. 

Note, in the first release of Java 5.0 the SuppressWarnings annotation is not yet supported.

LINK TO THIS Technicalities.FAQ002
REFERENCES What is the -Xlint:unchecked compiler option?
What is the SuppressWarnings annotation?

What is the -Xlint:unchecked compiler option?

The compiler option -Xlint:unchecked enables "unchecked" warnings, the option -Xlint:-unchecked disables all unchecked warnings.
"unchecked" warnings are by default disabled.  If you compile a program with no particular compiler options then the compiler will not report any "unchecked" warnings. If the compiler finds source code for which it would want to report an "unchecked" warning it only gives a general hint.  You will find the following note at the end of the list of all other errors and warnings: 
Note: util/Wrapper.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
If you want to see the "unchecked" warnings you must start the compiler with the -Xlint:unchecked option. 

Example (of globally enabling unchecked warnings): 

javac -Xlint:unchecked util/Wrapper.java
The option -Xlint:unchecked en ables the "unchecked" warnings. The "unchecked" warnings are also enabled when you use the -Xlint:all option. 

The option -Xlint:-unchecked disables the "unchecked" warnings.  This is useful to suppress all  "unchecked" warnings, while other types of warnings remain enabled. 

Example (of globally disabling unchecked warnings): 

javac -g -source 1.5 -Xlint:all -Xlint:-unchecked util/Wrapper.java
In this example, using -Xlint:all all warnings (such as "unchecked", "deprecated", "fallthrough", etc.) are enabled and subsequently the "unchecked" warnings are disabled using -Xlint:-unchecked . As a result all warnings except "unchecked" warnings will be reported.
LINK TO THIS Technicalities.FAQ003
REFERENCES What is an "unchecked" warning?
What is the SuppressWarnings annotation?

What is the SuppressWarnings annotation?

A standard annotation that suppresses warnings for the annotated part of the program.
The compiler supports a number of standard annotations (see package java.lang.annotation ). Among them is the SuppressWarnings annotation. It contains a list of warning labels.  If a definition in the source code is annotated with the SuppressWarnings annotation, then all warnings, whose labels appear in the annotation's list of warning labels, are suppressed for the annotated definition or any of its parts. 

The SuppressWarnings annotation can be used to suppress any type of labelled warning.  In particular we can use the annotation to suppress "unchecked" warnings. 

Example (of suppressing unchecked warnings): 

@SuppressWarnings("unchecked")
class Wrapper<T> {
  private T wrapped ;
  public Wrapper (T arg) {wrapped = arg;}
  ...
  p ublic Wrapper <T> clone() {
    Wrapper<T> clon = null;
     try { 
       clon = (Wrapper<T>) super.clone(); // unchecked warning supressed
     } catch (CloneNotSupportedException e) { 
       throw new InternalError();
     }
     try { 
       Class<?> clzz = this.wrapped.getClass();
       Method   meth = clzz.getMethod("clone", new Class[0]);
       Object   dupl = meth.invoke(this.wrapped, new Object[0]);
       clon.wrapped = (T) dupl; // unchecked warning supressed
     } catch (Exception e) {}
     return clon;
  }
}
This example would usually raise 2 "unchecked" warnings.  Since we annotated the entire class, all unchecked warnings raised anywhere in the class implementation are suppressed. 

We can suppress several types of annotations at a time.  In this case we must specify a list of warning labels.

Example (of suppressing several types of warnings): 

@SuppressWarnings(value={"unchecked","deprecation"})
public static void someMethod() {
  ...
  TreeSet se t = new TreeSet();
  set.add(new Date(104,8,11));     // unchecked and deprecation warning suppressed
  ...
}
This example would usually raise 2 warnings when the call to method add is compiled: 
warning: [deprecation] Date(int,int,int) in java.util.Date has been deprecated
        set.add(new Date(104,8,11));
                ^
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.TreeSet
        set.add(new Date(104,8,11));
 The annotation preceding the enclosing method suppresses all unchecked and deprecation warnings anywhere in the method implementation. 

Annotations can not be attached to statements, expressions, or blocks, only to program entities with a definition like types, variables, etc. 

Example (of illegal placement of annotation): 

public static void someMethod() {
  ...
  TreeSet se t = new TreeSet(); 
  @SuppressWarnings(value={"unchecked"}) // error
  set.add(new Date(104,8,11)); 
  ...
}
Annotations can be attached to the definition of packages, classes, interfaces, fields, methods, parameters, constructors, local variables, enum types, enum constants, and  annotation types. An annotated package declaration must go into a file named package-info.java in the directory that represents the package. 

Note, in release of Java 5.0 the SuppressWarnings annotation is not yet supported by all compilers. Sun's compiler will support in in release 6.0. 

LINK TO THIS Technicalities.FAQ004
REFERENCES What is an "unchecked" warning?
How can I disable or enable unchecked warnings?

How can I avoid "unchecked cast" warnings?

By using an unbounded wildcard parmeterized type as target type of a cast expression.
Occasionally, we would like to cast to a parameterized type, just to discover that the compiler flags it with an "unchecked" warning. As we are interested in warning-free compilation of our source code, we would like to avoid this warning.  Use of an unbounded wildcard parameterized type instead of a concrete or a bounded wildcard parameterized type would help avoid the warning. 

A typical example is the implementation of methods such as the equals method, that take Object reference and where a cast down to the actual type must be performed. 

Example (not recommended): 

class Wrapper<T> {
  private T wrapped;
    ...
  public boolean equals (Object other) {
    ...
    Wrapper<T> otherWrapper = (Wrapper<T>) other; // warning; unchecked cast
    return (this.wrapped.equals(otherWrapper.wrapped));
  }
}
When we replace the cast to Wrapper<T> by a cast to Wrapper<?> the warning disappears, because unbounded wildcard parameterized types are permitted as target type of a cast without any warnings. 

Example (implementation of equals ): 

class Wrapper<T> {
  private T wrapped;
    ...
  public boolean equals (Object other) {
    ...
    Wrapper<?> otherWrapper = (Wrapper<?>) other;
    return (this.wrapped.equals(otherWrapper.wrapped));
  }
}
Note, this technique works in this example only because we need no write access to the fields of the object refered to through the wildcard parameterized type and we need not invoke any methods.  Remember, use of the object that a wildcard reference variable refers to is restricted.  In other situations use of a wildcard parameterized type might not be a viable solution, because full access to the referenced object is needed. 
LINK TO THIS Technicalities.FAQ005
REFERENCES Can I cast to a parameterized type?
What is an "unchecked" warning?
How can I disable or enable unchecked warnings?
How do I best implement the equals method of a generic type?

Is it possible to eliminate all "unchecked" warnings?

Almost.
"Unchecked" warnings stem either from using generic types in their raw form or from casts whose target type is a type parameter or a concrete or bounded wildcard parameterized type. If you refrain from both using raw types and the critical casts you can theoretically eliminate all "unchecked" warnings.  Whether this is doable in practice depends on the circumstances. 

Raw types.

When source code is compiled for use in Java 5.0 that was developed before Java 5.0 and uses classes that are generic in Java 5.0, then "unchecked" warnings are inevitable.  For instance, if "legacy" code uses types such as List , which used to be a regular (non-generic) types before Java 5.0, but are generic in Java 5.0, all these uses of List are considered uses of a raw type in Java 5.0.  Use of the raw types will lead to "unchecked" warnings.  If you want to eliminate the "unchecked" warnings you must re-engineer the "legacy" code and replace all raw uses of List with appropriate instantiations of List such as List<String> , List<Object> , List<?> , etc.  All "unchecked" warnings can be eliminated this way. 

In source code developed for Java 5.0 you can prevent "unchecked" warnings in the first place by never using raw types.  Always provide type arguments when you use a generic type.  There are no situations in which you are forced to use a raw type.  In case of doubt, when you feel you have no idea which type argument would be appropriate, try the unbounded wildcard " ? ". 

In essence, "unchecked" warnings due to use of raw types can be eliminated if you have access to legacy code and are willing to re-engineer it. 

Casts.

"Unchecked" warnings as a result of cast expressions can be eliminated by eliminating the offensive casts.  Eliminating such casts is almost always possible.  There are, however, a few situations where a cast to a type parameter or a concrete or bounded wildcard parameterized type cannot be avoided. 

These are typically situations where a method returns a supertype reference to an object of a more specific type. The classic example is the clone method; it returns an Object reference to an object of the type on which it was invoked. In order to recover the returned object's actual type a cast in necessary.  If the cloned object is of a parameterized type, then the target type of the cast is an instantiation of that parameterized type, and an "unchecked" warning is inevitable.  The clone method is just one example that leads to unavoidable "unchecked" warnings. Invocation of methods via reflection has similar effects because the return value of a reflectively invoked method is returned via an Object reference.  It is likely that you will find further examples of unavoidable "unchecked" casts in practice. For a detailed discussion of an example see Technicalities.FAQ502 , which explains the implementation of a clone method for a generic class. 

In sum, there are situations in which you cannot eliminate "unchecked" warnings due to a cast expression. 
 

LINK TO THIS Technicalities.FAQ006
REFERENCES What is an "unchecked" warning?
How do I best implement the clone method of a generic type?

Why do I get an "unchecked" warning although there is no type information missing?

Because the compiler performs all type checks based on the type erasure when you use a raw type.
Usually the compiler issues an "unchecked" warning in order to alert you to some type-safety hazard that the compiler cannot prevent because there is not enough type information available. One of these situations is the invocation of methods of a raw type.

Example (of unchecked warning in conjunction with raw types): 

class TreeSet<E> {
  boolean add(E o) { ...  }
}
TreeSet se t = new TreeSet();
set.add("abc");        // unchecked warning

warning: [unchecked] unchecked call to add(E) as a member of the raw type TreeSet
               set.add("abc"); 
                      ^
When the add method is invoked the compiler does not know whether it is safe to add a String object to the collection because the raw type  TreeSet does not provide any information regarding the type of the contained elements.

Curiously, an unchecked warning is also issued in situations where there is enough type information available.

Example (of a spurious unchecked warning in conjunction with raw types):
 

class SomeType<T> {
  public List<String> getList() { ...  }
}
SomeType raw = new  SomeType ();
List<String> listString = raw.getList();  // unchecked warning

warning: [unchecked] unchecked conversion
found   : List
required: List<String>
        List<String> listString = raw.getList(); 
                                             ^
In this example, there is no type information missing.  The  getList method is declared to return a  List<String> and this is so even in the raw type because the method does not depend on the enclosing class's type parameter.  Yet the compiler complains. 

The reason is that the compiler computes the type erasure of a generic type when it finds an occurrence of the raw type in the source code.  Type erasure does not only elide all occurances of the type parameter  T , but also elides the type argument of the  getList method's return type. After type erasure, the  getList method returns just a  List and no longer a  List<String> .  All subsequent type checks are performed based on the type erasure; hence the "unchecked" warning.

The "unchecked" warning can easily be avoided by refraining from use of the raw type.  SomeType is a generic type and should always be used with a type argument. In general, the use of raw types will inevitably result in "unchecked" warnings; some of the warnings may be spurious, but most of them are justified. 


Note, that no spurious warning is issued when the method in question is a static method.

Example (of invoking a static method of a raw type):
 

class SomeType<T> {
  public  static List<String> getList() { ...  }
}
SomeType raw = new  SomeType ();
List<String> listString = raw.getList();  // fine
LINK TO THIS Technicalities.FAQ007
REFERENCES What is an "unchecked" warning?
Should I prefer parameterized types over raw types?
Why shouldn't I mix parameterized and raw types, if I feel like it?

 
 

Heap Pollution

What is heap pollution?
 
A situation where a variable of a parameterized type refers to an object that is not of that parameterized type. 
It can happen that a variable of a parameterized type such as  List<String> refers to an object that is not of that parameterized type. 

Example (of heap pollution):
 

List ln = new ArrayList<Number>();
List<String> ls =ln;  // unchecked warning
String s = ls.get(0); // ClassCastException


After the assignment of the reference variable  ln to the reference variable ls , the  List<String> variable will point to a  List<Number> object. Such a situation is called  heap pollution and is usually indicated by an unchecked warning.  A polluted heap is likely to lead to an unexpected  ClassCastException at runtime.  In the example above, it will lead to a  ClassCastException , when a object is retrieved from the  List<String> and assigned to a  String variable, because the object is a  Number , not a  String .

LINK TO THIS Technicalities.FAQ050
REFERENCES What is an "unchecked" warning?
When does heap pollution occur?

When does heap pollution occur?
 
As a result of mixing raw and parameterized type, unwise casting, and separate compilation.
Heap pollution occurs in three situations:
  • mixing raw types and parameterized types
  • performing unchecked casts
  • separate compilation of translation units
With the exception of separate compilation, the compiler will always issue an unchecked warning to draw your attention to the potential heap pollution. If you co-compile your code without warnings then no heap pollution can ever occur. 

Raw Types

Heap pollution can occur when raw types and parameterized types are mixed and a raw type variable is assigned to a parameterized type variable.  Note, that heap pollution does not necessarily occur, even if the compiler issues an unchecked warning.

Example (of mixing raw and parameterized types):

List ln = new ArrayList<Number>();
List ls = new LinkedList<String>();

List<String> list;
list = ln; // unchecked warning + heap pollution
list = ls; // unchecked warning + NO heap pollution

The first assignment leads to heap pollution, because the List<String> variable would then point to a List<Number> .  The second assignment does not result in heap pollution, because the raw type variable on the right-hand side of the assignment refers to a List<String> , which matches the parameterized type on the left-hand side of the assignment.

Mixing raw and parameterized types should be avoided, if possible.  It cannot be avoided when non-generic legacy code is combined with modern generic code. But otherwise, the mix is bad programming style.



Unchecked Casts

Unwise casting can lead to all kinds of unhealthy situations.  In particular, in can lead to heap pollution.

Example (of cast to parameterized type polluting the heap):

List<? extends Number> ln = new ArrayList<Long>();
List<Short> ls = (List<Short>) ln; // unchecked warning + heap pollution
List<Long>  ll = (List<Long>)  ln; // unchecked warning + NO heap pollution
The compiler permits the two casts in the example above, because List<? extends Number> is a supertype of the types List<Short> and List<Long> . The casts are similar to casts from supertype Object to subtype Short or Long .  The key difference is that the correctness of a cast to a non-parameterized type can be ensured at runtime and will promptly lead to ClassCastException , while a cast to a parameterized type cannot be ensured at runtime because of type erasure and might results in heap pollution.

Casts with a parameterized target type can lead to heap pollution, and so do casts to type variables.

Example (of cast to type variable polluting the heap):
 

<S,T> S convert(T arg) {
   return (S)arg; // unchecked warning
}
Number n = convert(new Long(5L)); // fine
String s = convert(new Long(5L)); // ClassCastException


In this example we do not cast to a parameterized type, but a type variable S .  The compiler permits the cast because the cast could succeed, but there is no way to ensure success of the cast at runtime.

Casts, whose target type is a parameterized type or a type variable, should be avoided, if possible. 


Separate Compilation

Another situation, in which heap pollution can occur is separate compilation of translation units. 

Example (initial implementation):
 

file FileCrawler.java :
final class FileCrawler {
    ...
    public List<String> getFileNames() {
        List<String> list = new LinkedList<String>();
        ...
        return list;
    }
}
file Test . java :
final class Test {
    public static void main(String[] args) {
        FileCrawler crawler = new FileCrawler("http:\\www.goofy.com");
        List<String> files = crawler.getFileNames(); 
        System.out.println(files.get(0));
    }
}
The program compiles and runs fine.  Now, let's assume that we modify the FileCrawler implementation.  Instead of returning a List<String> we return a List<StringBuilder> .  Note, the other class is not changed at all.

Example (after modification and co-compilation):
 

file FileCrawler.java :
final class FileCrawler {
    ...
    public List<StringBuilder> getFileNames() {
        List<StringBuilder> list = new LinkedList<StringBuilder>();
        ...
        return list;
    }
}
file Test . java :
final class Test {
    public static void main(String[] args) {
        FileCrawler crawler = new FileCrawler("http:\\www.goofy.com");
        List<String> files = crawler.getFileNames(); // error
        System.out.println(files.get(0));
    }
}
When we co-compile both translation units, the compiler would report an error in the unmodified file Test.java because the return type of the getNames() method does no longer match the expected type List<String> .

If we compiler separately, that is, only compile the modified file Test.java , then no error would be reported.   This is because the class, in which the error occurs, has not been re-compiled.  When the program is executed, a ClassCastException will occur.

Example (after modification and  separate compilation):
 

file FileCrawler.java :
final class FileCrawler {
    ...
    public List<StringBuilder> getFileNames() {
        List<StringBuilder> list = new LinkedList<StringBuilder>();
        ...
        return list;
    }
}
file Test . java :
final class Test {
    public static void main(String[] args) {
        FileCrawler crawler = new FileCrawler("http:\\www.goofy.com");
        List<String> files = crawler.getFileNames(); // fine
        System.out.println(files.get(0));          // ClassCastException
    }
}
This is another example of heap pollution.  The compiler, since it does not see the entire program, but only a part of it, cannot detect the error.  Co-compilation  avoids this problem and enables the compiler to detect and report the error.

Separate compilation in general is hazardous, independently of generics.  If you provide a method that first returns a String and later you change it to return a StringBuilder , without re-compiling all parts of the program that use the method, you end up in a similarly disastrous situation.  The crux is the incompatible change of the modified method.  Either you can make sure that the modified part is co-compiled with all parts that use it or you must not introduce any incompatible changes such as changes in semantics of types or signatures of methods. 

LINK TO THIS Technicalities.FAQ051
REFERENCES What is heap pollution?
What is an "unchecked" warning?
How can I avoid "unchecked cast" warnings?
Is it possible to eliminate all "unchecked" warnings?

Type Erasure

How does the compiler translate Java generics?
 
By creating one unique byte code representation of each generic type (or method) and mapping all instantiations of the generic type (or method) to this unique representation.
The Java compiler is responsible for translating Java source code that contains definitions and usages of generic types and methods into Java byte code that the virtual machine can interpret. How does that translation work? 

A compiler that must translate a generic type or method (in any language, not just Java) has in principle two choices: 

  • Code specialization. The compiler generates a new representation for every instantiation of a generic type or method. For instance, the compiler would generate code for a list of integers and additional, different code for a list of strings, a list of dates, a list of buffers, and so on. 

  • Code sharing. The compiler generates code for only one representation of a generic type or method and maps all the instantiations of the generic type or method to the unique representation, performing type checks and type conversions where needed. 

    Code specialization is the approach that C++ takes for its templates:
    The C++ compiler generates executable code for every instantiation of a template. The downside of code specialization of generic types is its potential for code bloat.  A list of integers and a list of strings would be represented in the executable code as two different types. Note that code bloat is not inevitable in C++ and can generally be avoided by an experienced programmer. 

    Code specialization is particularly wasteful in cases where the elements in a collection are references (or pointers), because all references (or pointers) are of the same size and internally have the same representation. There is no need for generation of mostly identical code for a list of references to integers and a list of references to strings.  Both lists could internally be represented by a list of references to any type of object. The compiler just has to add a couple of casts whenever these references are passed in and out of the generic type or method. Since in Java most types are reference types, it deems natural that Java chooses code sharing as its technique for translation of generic types and methods. 

    The Java compiler applies the code sharing technique and creates one unique byte code representation of each generic type (or method).  The various instantiations of the generic type (or method) are mapped onto this unique representation by a technique that is called type erasure

    LINK TO THIS Technicalities.FAQ100
    REFERENCES What is type erasure?

    What is type erasure?

    A process that maps a parameterized type (or method) to its unique byte code representation by eliding type parameters and arguments.
    The compiler generates only one byte code representation of a generic type or method and maps all the instantiations of the generic type or method to the unique representation. This mapping is performed by type erasure.  The essence of type erasure is the removal of all information that is related to type parameters and type arguments. In addition, the compiler adds type checks and type conversions where needed and inserts synthetic bridge methods if necessary. It is important to understand type erasure because certain effects related to Java generics are difficult to understand without a proper understanding of the translation process. 

    The type erasure process can be imagined as a translation from generic Java source code back into regular Java code.  In reality the compiler is more efficient and translates directly to Java byte code.  But the byte code created is equivalent to the non-generic Java code you will be seeing in the subsequent examples. 

    The steps performed during type erasure include: 

    Eliding type parameters.
    When the compiler finds the definition of a generic type or method, it removes all occurrences of the type parameters and replaces them by their leftmost bound, or type Object if no bound had been specified. 

    Eliding type arguments.
    When the compiler finds a paramterized type, i.e. an instantiation of a generic type, then it removes the type arguments. For instance, the types List<String> , Set<Long> , and Map<String,?> are translated to List , Set and Map respectively. 

    Example (before type erasure): 

    interface Comparable <A> {
      public int compareTo( A that);
    }
    final class NumericValue implements Comparable <NumericValue> {
      priva te byte value; 
      public  NumericValue (byte value) { this.value = value; } 
      public  byte getValue() { return value; } 
      public  int compareTo( NumericValue t hat) { return this.value - that.value; }
    }
    class Collections { 
      public static <A extends Comparable<A>>A max(Collection <A> xs) {
        Iterator <A> xi = xs.iterator();
        A w = xi.next();
        while (xi.hasNext()) {
          A x = xi.next();
          if (w.compareTo(x) < 0) w = x;
        }
        return w;
      }
    }
    final class Test {
      public static void main (String[ ] args) {
        LinkedList <NumericValue> numberList = new LinkedList <NumericValue> ();
        numberList .add(new NumericValue((byte)0)); 
        numberList .add(new NumericValue((byte)1)); 
        NumericValue y = Collections.max( numberList ); 
      }
    }
    Type parameters are green and type arguments are blue .  During type erasure the type arguments are discarded and the type paramters are replaced by their leftmost bound. 

    Example (after type erasure): 

    interface Comparable {
      public int compareTo( Object that);
    }
    final class NumericValue implements Comparable {
      priva te byte value; 
      public  NumericValue (byte value) { this.value = value; } 
      public  byte getValue() { return value; } 
      public  int compareTo( NumericValue t hat)   { return this.value - that.value; }
      public  int compareTo(Object that) { return this.compareTo((NumericValue)that);  }
    }
    class Collections { 
      public static Comparable max(Collection xs) {
        Iterator xi = xs.iterator();
        Comparable w = (Comparable) xi.next();
        while (xi.hasNext()) {
          Comparable x = (Comparable) xi.next();
          if (w.compareTo(x) < 0) w = x;
        }
        return w;
      }
    }
    final class Test {
      public static void main (String[ ] args) {
        LinkedList numberList = new LinkedList();
        numberList .add(new NumericValue((byte)0)); 
        numberList .add(new NumericValue((byte)1)); 
        NumericValue y = (NumericValue) Collections.max( numberList ); 
      }
    }
    The generic Comparable interface is translated to a non-generic interface and the unbounded type parameter A is replaced by type Object

    The NumericValue class implements the non-generic Comparable interface after type erasure, and the compiler adds a so-called bridge method . The bridge method is needed so that class NumericValue remains a class that implements the Comparable interface after type erasure. 

    The generic method max is translated to a non-generic method and the bounded type parameter A is replaced by its leftmost bound, namely Comparable .  The parameterized interface Iterator<A> is translated to the raw type Iterator and the compiler adds a cast whenever an element is retrieved from the raw type Iterator

    The uses of the parameterized type LinkedList<NumericValue> and the generic max method in the main method are translated to uses of the non-generic type and method and, again, the compiler must add a cast. 
     

    LINK TO THIS Technicalities.FAQ101
    REFERENCES What is a bridge method?
    Why does the compiler add casts when it translates generics?
    How does type erasure work when a type parameter has several bounds?

    What is reification?

    Representing type parameters and arguments of generic types and methods at runtime.  Reification is the opposite of  type erasure .
    In Java, type parameters and type arguments are elided when the compiler performs type erasure.  A side effect of type erasure is that the virtual machine has no information regarding type parameters and type arguments.  The JVM cannot tell the difference between a List<String> and a List<Date> .

    In other languages, like for instance C#, type parameters and type arguments of generics types and methods do have a runtime representation. This representation allows the runtime system to perform certain checks and operations based on type arguments.  In such a language the runtime system can tell the difference between a List<String> and a List<Date> .

    LINK TO THIS Technicalities.FAQ101A
    REFERENCES What is type erasure?
    What is a reifiable type?

    What is a bridge method?

    A synthetic method that the compiler generates in the course of type erasure.  It is sometimes needed when a type extends or implements a parameterized class or interface.
    The compiler insert bridge methods in subtypes of parameterized supertypes to ensure that subtyping works as expected. 

    Example (before type erasure): 

    interface Comparable <A> {
      public int compareTo( A that);
    }
    final class NumericValue implements Comparable <NumericValue> {
      priva te byte value; 
      public  NumericValue (byte value) { this.value = value; }
      public  byte getValue() { return value; } 
      public  int compareTo( NumericValue t hat) { return this.value - that.value; }
    }
    In the example, class NumericValue implements interface Comparable<NumericValue> and must therefore override the superinterface's compareTo method.  The method takes a NumericValue as an argument. In the process of type erasure, the compiler translates the parameterized Comparable<A> interface to its type erased counterpart Comparable .  The type erasure changes the signature of the interface's compareTo method.  After type erasure the method takes an Object as an argument. 

    Example (after type erasure): 

    interface Comparable {
      public int compareTo( Object that);
    }
    final class NumericValue implements Comparable {
      priva te byte value; 
      public  NumericValue (byte value) { this.value = value; } 
      public  byte getValue() { return value; } 
      public  int compareTo( NumericValue t hat)   { return this.value - that.value; }
      public  int compareTo(Object that) { return this.compareTo((NumericValue)that);  }
    }
    After this translation, method  NumericValue.compareTo(NumericValue) is no longer an implementation of the interface's compareTo method.  The type erased Comparable interface requires a compareTo method with argument type Object , not NumericValue . This is a side effect of type erasure: the two methods (in the interface and the implementing class) have identical signatures before type erasure and different signatures after type erasure. 

    In order to achieve that class NumericValue remains a class that correctly implements the Comparable interface, the compiler adds a bridge method to the class.  The bridge method has the same signature as the interface's method after type erasure, because that's the method that must be implemented. The bridge method delegates to the orignal methods in the  implementing class. 


    The existence of the bridge method does not mean that objects of arbitrary types can be passed as arguments to the compareTo method in NumericValue .  The bridge method is an implementation detail and the compiler makes sure that it normally cannot be invoked. 

    Example (illegal attempt to invoke bridge method): 

    NumericValue value = new NumericValue((byte)0);
    value.compareTo(value);  // fine
    value.compareTo("abc");  // error
    The compiler does not invoke the bridge method when an object of a type other than NumericValue is passed to the compareTo method. Instead it rejects the call with an error message, saying that the compareTo method expects a NumericValue as an argument and other types of arguments are not permitted. 

    You can, however, invoke the synthetic bridge message using reflection.  But, if you provide an argument of a type other than NumericValue , the method will fail with a ClassCastException thanks of the cast in the implementation of the bridge method. 

    Example (failed attempt to invoke bridge method via reflection): 

    int reflectiveCompareTo(NumericValue value, Object other)
      throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
    {
      Method meth = NumericValue.class.getMethod("compareTo", new Class[]{Object.class});
      return (Integer)meth.invoke(value, new Object[]{other}); 
    }
    NumericValue value = new NumericValue((byte)0);
    reflectiveCompareTo(value, value);  // fine
    reflectiveCompareTo(value,"abc");   // ClassCastException
    The cast to type NumericValue in the bridge method fails with a ClassCastException   when an argument of a type other than NumericValue is passed to the bridge method.  This was it is guaranteed that a bridge method, even when it is called, will fail for unexpected argument types.
    LINK TO THIS Technicalities.FAQ102
    REFERENCES What is type erasure?
    Under which circumstances is a bridge method generated?

    Under which circumstances is a bridge method generated?

    When a type extends or implements a parameterized class or interface and type erasure changes the signature of any inherited method.
    Bridge methods are necessary when a class implements a parameterized interface or extends a parameterized superclass and type ersure changes the argument type of any of the inherited non-static methods. 

    Below is an example of a class that extends a parameterized superclass.

    Example (before type erasure): 

    class Superclass <T extends Bound> {
      public void m1( T arg) { ... }
      public T m2() { ... }
    }
    class Subclass extends Superclass <SubTypeOfBound> {
       public void m1( SubTypeOfBound arg) { ... }
       public SubTypeOfBound m 2() { ... }
    Example (after type erasure): 
    class Superclass {
      void m1( Bound arg) { ... }
      Bound m2() { ... }
    }
    class Subclass extends Superclass {
      public void m1(SubTypeOfBound arg) { ... }
      public void m1(Bound arg) { m1((SubTypeOfBound)arg); }
      public SubTypeOfBound m2() { ... }
      public Bound          m2() { return m2(); }
    Type erasure changes the signature of the superclass's methods.  The subclass's methods are no longer overriding versions of the superclass's method after type erasure. In order to make overriding work the compiler adds bridge methods. 

    The compiler must add bridge methods even if the subclass does not override the inherited methods. 

    Example (before type erasure): 

    class Superclass <T extends Bound> {
      public void m1( T arg) { ... }
      public T m2() { ... }
    }
    class AnotherSubclass extends Superclass <SubTypeOfBound> {
    }
    Example (after type erasure): 
    class Superclass {
      void m1( Bound arg) { ... }
      Bound m2() { ... }
    }
    class AnotherSubclass extends Superclass {
      public void  m1(Bound arg) { super.m1((SubTypeOfBound)arg); }
      public Bound m2() { return super.m2(); }
    }
    The subclass is derived from a particular instantiation of the superclass and therefore inherits the methods with a particular signature.  After type erasure the signature of the superclass's methods are different from the signatures that the subclass is supposed to have inherited.  The compiler adds bridge methods, so that the subclass has the expected inherited methods. 

    No bridge method is needed when type erasure does not change the signature of any of the methods of the parameterized supertype.  Also, no bridge method is needed if the signatures of methods in the sub- and supertype change in the same way.  This can occur when the subtype is generic itself. 

    Example (before type erasure): 

    interface Callable <V> {
      public V call();
    }
    class Task <T> implements Callable <T> {
      public T call() { ... }
    }
    Example (after type erasure):
    interface Callable {
      public Object call();
    }
    class Task implements Callable {
      public Object call() { ... }
    }
    The return type of the call method changes during type erasure in the interface and the implementing class.  After type erasure the two methods have the same signature so that the subclass's method implements the interface's method without a brdige method. 

    However, it does not suffice that the subclass is generic.  The key is that the method signatures must not match after type erasure.  Otherwise, we again need a bridge method. 

    Example (before type erasure): 

    interface Copyable <V> extends Cloneable {
      public V copy();
    }
    class Triple <T extends Copyable<T>> implements Copyable <Triple<T>> {
      public Triple<T> copy() { ... }
    }
    Example (after type erasure): 
    interface Copyable extends Cloneable {
      public Object copy();
    }
    class Triple implements Copyable {
      public Triple copy() { ... }
      public Object copy() { return copy(); }
    }
    The method signatures change to Object copy() in the interface and Triple copy() in the subclass. As a result, the compiler adds a bridge method.
    LINK TO THIS Technicalities.FAQ103
    REFERENCES What is type erasure?

    Why does the compiler add casts when it translates generics?

    Because the return type of methods of a parameterized type might change as a side effect of type erasure.
    During type erasure the compiler replaces type parameters by the leftmost bound, or type Object if no bound was specified. This means that methods whose return type is the type parameter would return a reference that is either the leftmost bound or Object , instead of the more specific type that was specified in the parameterized type and that the caller expects.  A cast is need from the leftmost bound or Object down to the more specific type.. 

    Example (before type erasure): 

    public class Pair<X,Y> {
      private X first;
      private Y second;
      public Pair(X x, Y y) {
        first = x;
        second = y;
      }
      public X getFirst() { return first; }
      public Y getSecond() { return second; }
      public void setFirst(X x) { first = x; }
      public void setSecond(Y y) { second = y; }
    }

    final class Test {
      public static void main(String[] args) {
        Pair<String,Long> pair = new Pair<String,Long>("limit", 10000L);
        String s = pair.getFirst();
        Long   l = pair.getSecond();
        Object o = pair.getSecond();
      }
    }

    Example (after type erasure): 
    public class Pair {
      private Object first;
      private Object second;
      public Pair( Object x, Object y) {
        first = x;
        second = y;
      }
      public Object getFirst() { return first; }
      public Object getSecond() { return second; }
      public void setFirst( Object x) { first = x; }
      public void setSecond( Object y) { second = y; }
    }

    final class Test {
      public static void main(String[] args) {
        Pair pair = new Pair("limit", 10000L);
        String s = (String) pair.getFirst();
        Long   l = (Long)    pair.getSeond();
        Object o =          pair.getSecond();
      }
    }

    After type erasure the methods getFirst and getSecond of type Pair both have the return type Object .  Since the declared static type of the pair in our test case is Pair<String,Long> the caller of getFirst and getSecond expects a String and a Long as the return value.  Without a cast this would not work and in order to make it work the compiler adds the necessary casts from Object to String and Long respectively. 

    The inserted casts cannot fail at runtime with a ClassCastException because the compiler already made sure at compile-time that both fields are references to objects of the expected type.  The compiler would issue an error method if arguments of types other than String or Long had been passed to the constructor or the set methods.  Hence it is guarantees that these casts cannot fail. 

    In general, casts silently added by the compiler are guaranteed not to raise a ClassCastException if the program was compiled without warnings.  This is the type-safety guarantee. 

    Implicit casts are inserted when methods are invoked whose return type changed during type erasure. Invocation of methods whose argument type changed during type erasure do not require insertion of any casts.  For instance, after type erasure the setFirst and setSecond  methods of class Pair take Object arguments. Invoking them with arguments of a more specific type such as String and Long is possible without the need for any casts.

    LINK TO THIS Technicalities.FAQ104
    REFERENCES What is type erasure?
    What does type-safety mean?

    How does type erasure work when a type parameter has several bounds?

    The compiler adds casts as needed.
    In the process of type erasure the compiler replaces type parameters by their leftmost bound, or type Object if no bound was specified. How does that work if a type parameter has several bounds? 

    Example (before type erasure): 

    interface Runnable { 
      void run();
    }
    interface Callable<V> {
      V call();
    }
    class X<T extends Callable<Long> & Runnable> {
      private T task1, task2;
      ...
      public void do() { 
        task1.run(); 
        Long result = task2.call();
      }
    Example (after type erasure): 
    interface Runnable { 
      void run();
    }
    interface Callable {
      Object call();
    }
    class X {
      private Callable task1, task2;
      ...
      public void do() { 
        ( (Runnable) task1).run(); 
        Long result = (Long) task2.call();
      }
    }
    The type parameter T is replaced by the bound Callable , which means that both fields are held as references of type Callable .  Methods of the leftmost bound (which is Callable in our example) can be called directly.  For invocation of methods of the other bounds ( Runnable in our example) the compiler adds a cast to the respective bound type, so that the methods are accessible. The inserted cast cannot fail at runtime with a ClassCastException because the compiler already made sure at compile-time that both fields are references to objects of a type that is within both bounds. 

     In general, casts silently added by the compiler are guaranteed not to raise a ClassCastException if the program was compiled without warnings.  This is the type-safety guarantee.

    LINK TO THIS Technicalities.FAQ105
    REFERENCES What does type-safety mean?

    What is a reifiable type?

    A type whose type information is fully available at runtime, that is, a type that does not lose information in the course of type erasure.
    As a side effect of type erasure, some type information that is present in the source code is no longer available at runtime.  For instance, parameterized types are translated to their corresponding raw type in a process called type erasure and lose the information regarding their type arguments. 

    For example, types such as List<String> or Pair<? extends Number, ? extends Number> are available to and used by the compiler in their exact form, including the type argument information.  After type erasure, the virtual machine has only the raw types List and Pair available, which means that part of the type information is lost. 

    In contrast, non-parameterized types such as java.util.Date or java.lang.Thread.State are not affected by type erasure.  Their type information remains exact, because they do not have type arguments. 

    Among the instantiations of a generic type only the unbounded wildcard instantiations, such as Map<?,?> or Pair<?,?> , are unaffected by type erasure.  They do lose their type arguments, but since all type arguments are unbounded wildcards, no information is lost. 

    Types that do NOT lose any information during type erasure are called reifiable types .  The term reifiable stems from  reification .  Reification means that type parameters and type arguments of generic types and methods are available at runtime.  Java does not have such a runtime representation for type arguments because of type erasure.  Consequently, the reifiable types in Java are only those types for which reification does not make a difference, that is, the types that do not need any runtime representation of type arguments.

    The following types are reifiable: 

    • primitive types
    • non-generic (or non-parameterized) reference types
    • unbounded wildcard instantiations
    • raw types
    • arrays of any of the above
    The non-reifiable types, which lose type information as a side effect of type erasure, are: 
    • instantiations of a generic type with at least one concrete type argument
    • instantiations of a generic type with at least one bounded wildcard as type argument
    Reifiable types are permitted in some places where non-reifiable types are disallowed.  Reifiable types are permitted (and non-reifiable types are prohibited): 
    • as type in an instanceof expression
    • as component type of an array
    LINK TO THIS Technicalities.FAQ106
    REFERENCES What is type erasure?
    What is reification?
    What is an unbounded wildcard parameterized type?
    What is the raw type?
    Which types can or must not appear as target type in an instanceof expression?
    Can I create an array whose component type is a concrete parameterized type?
    Can I create an array whose component type is a wildcard parameterized type?
    Why is it allowed to create an array whose component type is an unbounded wildcard parameterized type?

    What is the type erasure of a parameterized type?

    The type without any type arguments.
    The erasure of a parameterized type is the type without any type arguments (i.e. the raw type). This definition extends to arrays and nested types. 

    Examples: 

     
    parameterized type type erasure
    List<String> List
    Map.Entry<String,Long> Map.Entry
    Pair<Long,Long>[] Pair[]
    Comparable<? super Number> Comparable
    The type erasure of a non-parameterized type is the type itself.
    LINK TO THIS Technicalities.FAQ107
    REFERENCES What is the raw type?

    What is the type erasure of a type parameter?

    The type erasure of its leftmost bound, or type Object if no bound was specified.
    The type erasure of a type parameter is the erasure of its leftmost bound. The type erasure of an unbounded type parameter is type Object

    Examples: 

     
    type parameters type erasure
    <T> Object
    <T extends Number> Number
    <T extends Comparable<T>> Comparable
    <T extends Cloneable & Comparable<T>> Cloneable
    <T extends Object & Comparable<T>> Object
    <S, T extends S> Object,Object
    LINK TO THIS Technicalities.FAQ108
    REFERENCES What is a bounded type parameter?

    What is the type erasure of a generic method?

    A method with the same name and the types of all method parameters replaced by their respective type erasures.
    The erasure of a method signature is a signature consisting of the same name and the erasures of all the formal method parameter types. 

    Examples: 

     
    parameterized method type erasure
    Iterator<E> iterator() Iterator iterator()
    <T> T[] toArray(T[] a)  Object[] toArray(Object[] a)
    <U> AtomicLongFieldUpdater<U> 
    newUpdater(Class<U> tclass, String fieldName)
    AtomicLongFieldUpdater
    newUpdater(Class tclass,String fieldName)
    LINK TO THIS Technicalities.FAQ109
    REFERENCES What is type erasure?
    What is the type erasure of a parameterized type? 
    What is the type erasure of a type parameter?

    Is generic code faster or slower than non-generic code?

    There is no perceivable difference.
    Some programmers, especially those with a C++ background, expect that generic code should perform much faster than non-generic code, because this is one observable benefit of using templates in C++.  Other programmers assume that the synthetic bridge methods and implicit casts inserted by the compiler in the process of type erasure would degrade the runtime performance of generic code.  Which one is true? 

    The short answer is: it is likely that one will find neither a substantial difference in runtime performance nor any consistent trend.  However, this has not yet been verified by any benchmarks I know of.  Nevertheless, let us take a look at the various overlapping effects that might explain such a statement. 
     

    Implicit casts.

    The casts added by the compiler are exactly the casts that would appear in non-generic code.  Hence the implicit casts do not add any overhead. 
     
    Example (generic code): 
    List <String> list = new List <String> ();
    list.add("abc");
    String s = list.get(0);
    Example (after type erasure): 
    List list = new LinkedList();
    list.add("abc");
    String s = (String) list.get(0);
    Example (non-generic code): 
    List list = new LinkedList();
    list.add("abc");
    String s = (String) list.get(0);

    The non-generic code is exactly what the compiler generates in the process of type erasure, hence there is no difference in performance.
     

    Bridge methods.

    The compiler adds bridge methods. These synthetic methods cause an additional method invocation at runtime, they are represented in the byte code and increase its volume, and they add to the memory footprint of the program. 
     
    Example (generic code): 
    final class Byte implements Comparable <Byte> {
      priva te byte value; 
      public  Byte(byte value) { 
        this.value = value; 
      }
      public  byte byteValue() { return value; } 
      public  int compareTo( Byte t hat) { 
        return this.value - that.value; 
      }
    }
    Example (after type erasure): 
    final class Byte implements Comparable {
      priva te byte value; 
      public  Byte(byte value) { 
        this.value = value; 
      } 
      public  byte byteValue() { return value; } 
      public  int compareTo(Byte t hat)   { 
        return this.value - that.value; 
      }
      public  int compareTo(Object that) { 
        return this.compareTo((Byte)that); 
      }
    }
    Example (non-generic code):
    final class Byte implements Comparable {
      priva te byte value; 
      public  Byte(byte value) { 
        this.value = value; 
      } 
      public  byte byteValue() { return value; } 
      public  int compareTo( Object that) { 
        return this.value - ( (Byte) that).value; 
      }
    }

    It is likely that there is a slight performance penalty for the bridge method that affects runtime execution and class loading.  However, only new (i.e. 5.0) source code is affected.  If we compile legacy (i.e. 1.4-compatible) source code, there are no additional bridge methods and the byte code should be identical, more or less, to the way it was before. Most likely the slight performance penalty is compensated for by improvements in Hotspot. 
     

    Runtime type information.

    Static information about type parameters and their bounds is made available via reflection.  This runtime type information adds to the size of the byte code and the memory footprint, because the information must be loaded into memory at runtime.  Again, this only affects new (i.e. 5.0) source code.  On the other hand, there are some enhancements to reflection that apply even to existing language features, and those do require slightly larger class files, too. At the same time, the representation of runtime type information has been improved. For example, there is now an access bit for "synthetic" rather than a class file attribute, and class literals now generate only a single instruction. These things often balance out.  For any particular program you might notice a very slight degradation in startup time due to slightly larger class files, or you might find improved running time because of shorter code sequences.  Yet it is unlikely that one will find any large or consistent trends. 
     

    Compilation time.

    Compiler performance might decrease because translating generic source code is more work than translating non-generic source code.  Just think of all the static type checks the compiler must perform for generic types and methods.  On the other hand, the performance of a compiler is often more dominated by its implementation techniques rather than the features of the language being compiled.  Again,  it is unlikely that one will find any perceivable or measurable trends. 

    LINK TO THIS Technicalities.FAQ110
    REFERENCES How does the compiler translate Java generics?
    What is type erasure?
    What is a bridge method?
    Why does the compiler add casts when it translates generics?

    How do I compile generics for use with JDK <= 1.4?

    Use a tool like Retroweaver.
    Retroweaver is a Java bytecode weaver that enables you to take advantage of the new 1.5 language features in your source code, while still retaining compability with 1.4 virtual machines. Retroweaver rewrites class files so that they are compatible with older virtual machines. Check out http://sourceforge.net/projects/retroweaver .
    LINK TO THIS Technicalities.FAQ111
    REFERENCES How does the compiler translate Java generics?
    Retroweaver Download Page

     
     
     
     

    Type System

    How do parameterized types fit into the Java type system?

    Instantiations of generic types have certain super-subtype relationship among each other and have a type relationship to their respective raw type.  These type relationships are relevant for method invocation, assignment and casts.
    Relevance of type relationships and type converstion rules in practice.

    The type system of a programming language determines which types are convertible to which other types.  These conversion rules have an impact on various areas of a programming language.  One area where conversion rules and type relationships play role is casts and instanceof expressions.  Other area is assignment compatibility and method invocation, where argument and return value passing relies on convertibility of the involved types. 

    The type conversion rules determine which casts are accepted and which ones are rejected.  For example, the types String and Integer have no relationship and for this reason the compiler rejects the attempt of a cast from String to Integer , or vice versa.  In contrast, the types Number and Integer have a super-subtype relationship; Integer is a subtype of Number and Number is a supertype of Integer . Thanks to this relationship, the compiler accepts the cast from Number to Integer , or vice versa.  The cast from Integer to Number is not even necessary, because the conversion from a subtype to a supertype is considered an implicit type conversion, which need not be expressed explicitly in terms of a cast; this conversion is automatically performed by the compiler whenever necessary.  The same rules apply to  instanceof expressions. 

    The conversion rules define which types are assignment compatible.  Using the examples from above, we see that a String cannot be assigned to an Integer variable, or vice versa, due to the lack of a type relationship.  In contrast, an Integer can be assigned to a Number variable, but not vice versa.  A side effect of the super-subtype relationship is that we can assign a subtype object to a supertype variable, without an explicit cast anywhere.  This is the so-called widening reference conversion ; it is an implicit conversion that the compiler performs automatically whenever it is needed.  The converse, namely assignment of a supertype object to a subtype variable, is not permitted.  This is because the so-called narrowing reference conversion is not an implicit conversion.  It can only be triggered by an explicit cast. 

    The rules for assignment compatibility also define which objects can be passed to which method.  An argument can be passed to a method if its type is assignment compatible to the declared type of the method parameter. For instance, we cannot pass an Integer   to a method that asks for String , but we can pass an Integer to a method that asks for a Number .  The same rules apply to the return value of a method. 
     

    Super-subtype relationships of parameterized types.

    In order to understand how objects of parameterized types can be used in assignments, method invocations and casts, we need an understanding of the relationship that parameterized types have among each other and with non-parameterized types. And we need to know the related conversion rules. 

    We already mentioned super-subtype relationships and the related narrowing and  widening reference conversions .  They exist since Java was invented, that is, among non-generic types.  The super-subtype relationship has been extended to include parameterized types.  In the Java 5.0 type system super-subtype relationships and the related narrowing/widening reference conversions exist among parameterized types, too.  We will explain the details in separate FAQ entries.  Here are some initial examples to get a first impression of the impact that type relationships and conversion rules have on method invocation. 

    Consider a method whose declared parameter type is a wildcard parameterized type.  A wildcard parameterized type acts as supertype of all members of the type family that the wildcard type denotes. 

    Example (of widening reference conversion from concrete instantiation to wildcard instantiation): 

    void printAll( LinkedList<? extends Number> c) { ... }

    LinkedList<Long> l = new LinkedList<Long>();
    ...
    printAll(l);  // widening reference conversion

    We can pass a List<Long> as an argument to the printAll method that asks for a LinkedList<? extends Number> .  This is permitted thanks to the super-subtype relationship between a wildcard instantiation and a concrete instantiation.  LinkedList<Long> is a member of the type family denoted by LinkedList<? extends Number> , and as such a LinkedList<Long> is a subtype of LinkedList<? extends Number> .  The compiler automatically performs a widening conversion from subtype to supertype and thus allows that a LinkedList<Long> can be supplied as argument to the printAll method that asks for a LinkedList<? extends Number> .

    Note that this super-subtype relationship between a wildcard instantiation and a member of the type family that the wildcard denotes is different from inheritance. Inheritance implies a super-subtype relationship as well, but it is a special case of the more general super-subtype relationship that involves wildcard instantiations. 

    We know inheritance relationships from non-generic Java.  It is the relationship between a superclass and its derived subclasses, or a super-interface and its sub-interfaces, or the relationship between an interface and its implementing classes.  Equivalent inheritance relationships exists among instantiations of different generic types.  The prerequisite is that the instantiations must have the same type arguments.  Note that this situation differs from the super-subtype relationship mentioned above, where we discussed the relationship between wildcard instantiations and concrete instantiations of the same generic type, whereas we now talk of the relationship between instantiations of different generic types with identical type arguments. 

    Example (of widening reference conversion from one concrete parameterized type to another concrete parameterized type): 

    void printAll( Collection<Long> c) { ... }

    LinkedList<Long> l = new LinkedList<Long>();
    ...
    printAll(l);  // widening reference conversion

    The raw types Collection and LinkedList have a super-subtype relationship; Collection is a supertype of LinkedList .  This super-subtype relationship among the raw types is extended to the parameterized types, provided the type arguments are identical: Collection<Long> is a supertype of LinkedList<Long> , Collection<String> is a supertype of LinkedList<String> , and so on. 

    It is common that programmers believe that the super-subtype relationship among type arguments would  extend into the respective parameterized type.  This is not true. Concrete instantiations of the same generic type for different type arguments have no type relationship. For instance, Number is a supertype of Integer , but List<Number> is not a supertype of List<Integer> .  A type relationship among different instantiations of the same generic type exists only among wildcard instantiations and concrete instantiations, but never among concrete instantiations. 

    Example (of illegal attempt to convert between different concrete instantiations of the same generic type): 

    void printAll( LinkedList<Number> c) { ... }

    LinkedList<Long> l = new LinkedList<Long>();
    ...
    printAll(l);  // error; no conversion

    Due to the lack of a type relationship between LinkedList<Number> and LinkedList<Long> the compiler cannot convert the LinkedList<Long> to a LinkedList<Number> and the method call is rejected with an error message. 
     

    Unchecked conversion of parameterized types.

    With the advent of parameterized types a novel category of type relationship was added to the Java type system: the relationship between a parameterized type and the corresponding raw type. The conversion from a parameterized type to the corresponding raw type is a widening reference conversion like the conversion from a subtype to the supertype. It is an implicit conversion.  An example of such a conversion is the conversion from a parameterized type such as List<String> or List<? extends Number> to the raw type List .  The counterpart, namely the conversion from the raw type to an instantiation of the respective generic type, is the so-called  unchecked conversion . It is an automatic conversion, too, but the compiler reports an "unchecked conversion" warning.   Details are explained in separate FAQ entries.  Here are some initial examples to get a first impression of usefulness of unchecked conversions.  They are mainly permitted for compatibility between generic and non-generic source code. 

    Below is an example of a method whose declared parameter type is a raw type. The method might be a pre-Java-5.0 method that was defined before generic and parameterized types had been available in Java.  For this reason it declares List as the argument type.  Now, in Java 5.0, List is a raw type. 

    Example (of a widening reference conversion from parameterized type to raw type): 

    void printAll( List c) { ... }

    List<String> l = new LinkedList<String>();
    ...
    printAll(l);  // widening reference conversion

    Source code such as the one above is an example of a fairly common situation, where non-generic legacy code meets generic Java 5.0 code.  The printAll method is an example of legacy code that was developed before Java 5.0 and uses raw types.  If more recently developed parts of the program use instantiations of the generic type List , then we end up passing an instantiation such as List<String> to the printAll method that declared the raw type List as its parameter type.  Thanks to the type relationship between the raw type and the parameterized type, the method call is permitted. It involves an automatic widening reference conversion from the parameterized type to the raw type. 

    Below is an example of the conversion in the opposite direction.  We consider a method has a declared parameter type that is a parameterized type.  We pass a raw type argument to the method and rely on an unchecked conversion to make it work. 

    Example (of an unchecked conversion from raw type to parameterized type): 

    void printAll( List<Long> c) { ... }

    List l = new LinkedList();
    ...
    printAll(l);  // unchecked conversion

    Like the previous example, this kind of code is common in situation where generic and non-generic code are mixed. 

    The subsequent FAQ entries discuss details of the various type relationships and conversions among raw types, concrete parameterized types, bounded and unbounded wildcard parameterized types. 
     

    LINK TO THIS Technicalities.FAQ201
    REFERENCES What is the raw type?
    What is a wildcard parameterized type?
    Which super-subtype relationships exist among instantiations of generic types?
    How does the raw type relate to instantiations of the corresponding generic type?
    How do instantiations of a generic type relate to  instantiations of other generic types that have the same type argument?
    How do unbounded wildcard instantiations of a generic type relate to other instantiations of the same generic type?
    How do wildcard instantiations with an upper bound relate to other instantiations of the same generic type?
    How do wildcard instantiations with a lower bound relate to other instantiations of the same generic type?

    How does the raw type relate to instantiations of the corresponding generic type?
     
    The raw type is the supertype of all instantiations of the corresponding generic type.
    The raw types have the regular supertype-subtype relationship with other raw types. For illustration we use the collection classes and interfaces from the JDK (see package java.util ). 

    In addition, the raw types are supertypes of all concrete and all wildcard instantiations of the generic type. For instance, the raw type Collection is a supertype of all instantiations of the generic type Collection

     

    With both properties combined a raw type is the supertype of all instantiations of all its generic and non-generic subtypes.   For instance, the raw type Collection is a supertype of all instantiations of all generic collection classes. 


     

    Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. That is, every instantiation of a generic type can be converted to the corresponding raw type.  The reverse is permitted, too, for reasons of compatibility between generic and non-generic types.  It is the so-called unchecked conversion and is accompanied by an "unchecked" warning. In detail, the conversion from a raw type to a concrete or bounded wildcard instantiation of the corresponding generic type leads to a warning.  The conversion from the raw type to the unbounded wildcard instantiation is warning-free.

    LINK TO THIS Technicalities.FAQ202
    REFERENCES How do parameterized types fit into the Java type system?
    What is the raw type?
    What is a concrete paramterized type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parameterized type?
    Which super-subtype relationships exist among instantiations of generic types?

    How do instantiations of a generic type relate to  instantiations of other generic types that have the same type argument?

    An instantiation of a generic type is the supertype of all instantiations of generic subtypes that have the same type argument. 
    Instantiations of the generic types have supertype-subtype relationships with concrete instantiations of generic subtypes provided they all have the exact same type arguments. The example below uses the JDK collection types (see package java.util ) for illustration. 
     

    The diagram illustrates the super-subtype relationship among instantiations that have the same type argument.  The type argument can be a concrete type, but also a bounded or unbounded wildcard.  For instance, Collection<Number> is the supertype of List<Number> and LinkedList<Number> , Collection<? extends Number> is the supertype of List<? extends Number> and LinkedList<? extends Number> , Collection<?> is the supertype of List<?> and LinkedList<?> , and so on. 

    Type relationships to other concrete instantiations do not exist.  In particular, the supertype-subtype relationship among the type arguments does not extend to the instantiations.  For example, Collection<Number> is NOT a supertype of Collection<Long>

    Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. The reverse is not permitted.

    LINK TO THIS Technicalities.FAQ203
    REFERENCES How do parameterized types fit into the Java type system?
    What is the raw type?
    What is a concrete parameterized type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parmeterized type?
    Which super-subtype relationships exist among instantiations of generic types?

    How do unbounded wildcard instantiations of a generic type relate to other instantiations of the same generic type?

    An unbounded wildcard instantiation is the supertype of all instantiations of the generic type.
    The unbounded wildcard instantiation of a generic type is supertype of all concrete and all wildcard instantiations of the same generic type. 
    For instance, the unbounded wildcard instantiation Collection<?> is supertype of all instantiations of the generic type Collection .  The example below uses the JDK collection types (see package java.util ) for illustration. 

    At the same, an unbounded wildcard instantiation is supertype of all unbounded instantiations of any generic subtypes.  For instance, the unbounded wildcard instantiation Collection<?> is supertype of List<?> , LinkedList<?> , and so on. Both type relationships combined, an unbounded wildcard instantiation is supertype of all instantiations of the same generic type and of all instantiations of all its generic subtypes. 


     

    Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. The reverse is not permitted. 

    There is one special rules for unbounded wildcard instantiations: the conversion from a raw type to the unbounded wildcard instantiation is not an "unchecked" conversion, that is, the conversion from Collection   to Collection<?> does not lead to an "unchecked" warning.  This is different for concrete and bounded instantiations, where the conversion from the raw type to the concrete and bounded wildcard instantiation leads to an "unchecked" warning. 

    LINK TO THIS Technicalities.FAQ204
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subtype relationships exist among instantiations of parameterized types?
    What is the raw type?
    What is a concrete parmeterizd type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parameterized type?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    How do wildcard instantiations with an upper bound relate to other instantiations of the same generic type?

    A wildcard instantiation wild an upper bound is supertype of all instantiations of the same generic type where the type argument is a subtype of the upper bound.
    An upper bound wildcard instantiation is supertype of all concrete instantiations with type arguments that are subtypes of the upper bound, the upper bound itself being included. For instance, Collection<? extends Number> is supertype of Collection<Number> , Collection<Long> , Collection<Short> , etc., because Number , Long , and Short are subtypes (or same type) of Number . The underlying idea is: a subtype of the upper bound (e.g. Long ) belongs to the family of types that the wildcard (e.g. ? extends Number ) stands for and in this case the wildcard instantiation (e.g. Collection<? extends Number> ) is a supertype of the concrete instantiation on the subtype of the upper bound (e.g. Collection<Long> ). 

    At the same time, a wildcard instantiation with an upper bound is supertype of all generic subtypes that are instantiated on the same upper bound wildcard.  For instance, Collection<? extends Number> is supertype of Set<? extends Number> and ArrayList<? extends Number>

    The upper bound wildcard instantiation is also supertype of other upper bound wildcard instantiation with an upper bound that is a subtype of the own upper bound.  For instance, Collection<? extends Number> is supertype of Collection<? extends Long> and Collection<? extend Short> , because Long and Short are subtypes of Number

    Similarly, Collection<? extends Comparable<?>> is supertype of Collection<? extends Number> and Collection<? extends Delayed> , because Number is a subtype of Comparable<Number> , which is a subtype of Comparable<?> , and Delayed   (see java.util.concurrent.Delayed ) is a subtype of Comparable<Delayed> , which is a subtype of Comparable<?> . The idea is that if the upper bound of one wildcard is a supertype of the upper bound of another wildcard then the type family with the supertype bound includes the type family with the subtype bound.  If one family of types (e.g. ? extends Comparable<?>) includes the other (e.g. ? extends Number> and ? extends Delayed ) then the wildcard instantiation on the larger family (e.g. Collection<? extends Comparable<?>> ) is supertype of the wildcard instantiation of the included family (e.g. Collection<? extends Number> ). 

    All these type relationships combined make a bounded wildcard instantiation supertype of a quite a number of instantiations of the same generic type and subtypes thereof. 

    Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. The reverse is not permitted. 

    LINK TO THIS Technicalities.FAQ205
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subtype relationships exist among instantiations of parameterized types?
    What is the raw type?
    What is a concrete parameterized type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parameterized type?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    How do wildcard instantiations with a lower bound relate to other instantiations of the same generic type?

    A wildcard instantiation wild a lower bound is supertype of all instantiations of the generic type where the type argument is a supertype of the lower bound.
    A wildcard instantiation with a lower bound is supertype of all concrete instantiation with type arguments that are supertypes of the lower bound, the lower bound itself included. For instance, Collection<? super Number> is supertype of Collection<Number> , Collection<Serializable> , and Collection<Object> , because Number , Serializable and Object are supertypes (or same type) of Number . The underlying idea is: a supertype of the lower bound (e.g. Object ) belongs to the family of types that the wildcard (e.g. ? super Number ) stands for and in this case the wildcard instantiation (e.g. Collection<? super Number> ) is a supertype of the concrete instantiation on the supertype of the lower bound (e.g. Collection<Object> ). 

    At the same time, a wildcard instantiation with a lower bound is supertype of parameterized subtypes that are instantiated on the same lower bound wildcard.  For instance, Collection<? super Number> is supertype of Set<? super Number> and ArrayList<? super Number>

    The lower bound wildcard instantiation is also supertype of other lower bound wildcard instantiation with a lower bound bound that is a supertype of the own lower bound.  For instance, Collection<? super Number> is supertype of Collection<? super Serializable> , because Serializable is a supertype of Number .   The idea is that if the lower bound of one wildcard is a subtype of the lower bound of another wildcard then the type family with the subtype bound includes the type family with the supertype bound.  If one family of types (e.g. ? super Number) includes the other (e.g. ? super Serializable ) then the wildcard instantiation on the larger family (e.g. Collection<? super Number> ) is supertype of the wildcard instantiation of the included family (e.g. Collection<? super Serializable> ). 

    Regarding conversions, the usual reference widening conversion from subtype to supertype is allowed. The reverse is not permitted. 

    LINK TO THIS Technicalities.FAQ206
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subtype relationships exist among instantiations of parameterized types?
    What is the raw type?
    What is a concrete parameterized type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parameterized type?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    Which super-subtype relationships exist among instantiations of generic types?

    This is fairly complicated and the type relationships are best determined setting up tables as explained in this FAQ entry. 
    Super-subtype relationships among instantiations of generic types are determined by two orthogonal aspects. 

    On the one hand, there is the inheritance relationship between a supertype and a subtype. This is the usual notion of inheritance as we know it from non-generic Java.  For instance, the interface Collection is a supertype of the interface List .  This inheritance relationship is extended in analogy to instantiations of generic types, i.e. to parameterized types.  The prerequisite is that the instantiations must have identical type arguments.  An example is the supertype Collection<Long> and its subtype List<Long> . The rule is: as long as the type arguments are identical, the inheritance relationship among generic types leads to a super-subtype relationship among corresponding parameterized types. 

    On the other hand, there is a relationship based on the type arguments. The prerequisite is that at least one of the involved type arguments is a wildcard. For example, Collection<? extends Number> is a supertype of Collection<Long> , because the type Long is a member of the type family that the wildcard " ? extends Number " denotes. 

    This kind of type relationship also exists between two wildcard instantiations of the same generic type with different wildcards as type arguments. The prerequisite is that the type family denoted by one wildcard is a superset of the type family denoted by the other wildcard. For example, Collection<?> is a supertype of Collection<? extends Number> , because the family of types denoted by the wildcard " ? " is a superset of the family of types denoted by the wildcard " ? extends Number ".  The super-sub set relationship among the type arguments leads to a super-sub type relationship among corresponding instantiations of the same parameterized type.  The type relationship mentioned above, between a wildcard instantiation and a concrete instantiation of the same generic type, is a special case of this rule; you just interpret the concrete type argument as a type family with only one member, namely the concrete type itself. 

    Both effects - the super-subtype relationship due to inheritance and the super-subtype relationship due to type arguments - are combined and lead to a two-dimensional super-subtype relationship table.  The tables below use examples for illustration. 

    The vertical axis of the table lists parameterized types according to their inheritance relationship, starting with the supertype on the top to a subtype on the bottom. The horizontal axis lists type arguments according to their super-subset relationship of the type families they denote, starting with the largest type set on the lefthand side to the smallest type set on the righthand side. 
     
    ? ? extends Serializable ? extends Number Long
    Collection Collection<?> Collection<? extends Serializable> Collection<? extends Number> Collection<Long>
    List List<?> List<? extends Serializable> List<? extends Number> List<Long>
    ArrayList ArrayList<?> ArrayList<? extends Serializable> ArrayList<? extends Number> ArrayList<Long>

    If you pick a certain entry in the table, say List<? extends Serializable> , then the subtable to the bottom and to the right contains all subtypes of the entry. 

    Below is another example that involves lower bound wildcards. Again, the horizontal axis lists type arguments according to their super-subset relationship of the type families they denote, starting with largest set of types denoted by the unbounded wildcard " ? " over type families of decreasing size to a type set consisting of one concrete type. The difficulty with lower bound wildcards is that the super-subset relationship of the type families denoted by lower bound wildcards is slightly counter-intuitive to determine.  Details are discussed in a separate FAQ entry. 
     
    ? ? super Long ? super Number Object
    Collection Collection<?> Collection<? super Long> Collection<? super Number> Collection<Object>
    List List<?> List<? super Long> List<? super Number> List<Object>
    ArrayList ArrayList<?> ArrayList<? super Long> ArrayList<? super Number> ArrayList<Object>

    If you pick a certain entry in the table, say List<? super Long> , then the subtable to the bottom and to the right contains all subtypes of the entry and you would find information such as: ArrayList<? super Number> is a subtype of List<? super Long> .


    Generic Types With More Than One Type Parameter

    We have been setting up tables to determine the super-subtype relationships among different instantiations of different, yet related parameterized types.  These tables were two-dimensional because we took into account inheritance on the one hand and various values for a type argument on the other hand.  A similar technique can be applied to parameterized types with more than one type parameter. 

    The example below uses a generic class Pair with two type parameters.  The vertical axis lists the first type arguments order by their super-subset relationship from the largest type set to the smallest type set.  The horizontal axis does the same for the second type argument. 
     
    ? ? super Long ? super Number Object
    ? Pair<?,?> Pair<?,? super Long> Pair<?,? super Number> Pair<?,Object>
    ? extends Serializable Pair<? extends Serializable,?> Pair<? extends Serializable,? super Long> Pair<? extends Serializable ,? super Number> Pair<? extends Serializable,Object>
    ? extends Number Pair<? extends Number,?> Pair<? extends Number,? super Long> Pair<? extends Number,? super Number> Pair<? extends Number,Object>
    Long Pair<Long,?> Pair<Long,? super Long> Pair<Long,? super Number> Pair<Long,Object>

    Tables with more than two dimensions can be set up in analogy.  The key point is that you list generic types from supertype to subtype and type arguments from superset to subset. For this purpose you need to interpret type arguments as sets of types and determine their super-subtype relationships.  Note that the latter can be rather counter-intuitive in case of multi-level wildcards involving lower bounds.  Details are discussed in a separate FAQ entry.

    LINK TO THIS Technicalities.FAQ207
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subset relationships exist among wildcards?
    What is the raw type?
    What is a concrete parameterized type?
    What is a wildcard parameterized type?
    What is the unbounded wildcard parameterized type?

    Which super-subset relationships exist among wildcards?

    A super-subtype relationship between upper bounds leads to a super-subset relationship between the resulting upper bound wildcards, and vice versa for a lower bounds.
    A wildcard denotes a family (or set) of types. These type sets can have super-subset relationships, namely when one type set includes the other type set.  The super-subset relationship among wildcards determines the super-subtype relationships of instantiations of parameterized types using these wildcards as type arguments.  The super-subtype relationships among instantiations of parameterized types play an important role in method invocation, assignments, type conversions, casts and type checks (as was discussed in a previous FAQ entry). For this reason, we need to know how to determine the super-subset relationships among the type sets denoted by wildcards.

    Here are the rules:

    • The unbounded wildcard "?" denotes the set of all types and is the superset of all sets denoted by bounded wildcards.
    • A wildcard with an upper bound A denotes a superset of another wildcard with an upper bound B, if A is a super type of B.
    • A wildcard with a lower bound A denotes a superset of another wildcard with a lower bound B, if A is a sub type of B.
    • A concrete type denotes a set with only one element, namely the type itself.
    upper bound wildcards lower bound wildcards
    ? ?
    ? extends SuperType ? super SubType
    ? extends SubType ? super SuperType
    concrete type* 
    *either SubType or a subtype thereof
    concrete type* 
    *either SuperType or a supertype thereof

    Here are some examples illustrating the rules: 
     
    upper bound wildcards lower bound wildcards
    ? ?
    ? extends Serializable ? super Long
    ? extends Number ? super Number
    Long Serializable

    The wildcard " ? " denotes the largest possible type set, namely the set of all types.  It is the superset of all type sets. 

    Upper bound wildcards are fairly easy to understand, compared to lower bound wildcards.  The wildcard " ? extends Serializable "  denotes the family of types that are subtypes of Serializable , the type Serializable itself being included. Naturally, this type family is a subset of the type set denoted by the wildcard " ? ". 

    The wildcard " ? extends Number "  denotes the family of types that are subtypes of Number , the type Number itself being included. Since Number is a subtype of Serializable , the type family " ? extends Number " is a subset of the type family " ? extends Serializable ".  In other words, the super-sub type relationship between the upper bounds leads to a super-sub set   relationship between the resulting type sets. 

    The concrete type Long denotes a single-member type set, which is a subset of the type family " ? extends Number " because Long is a subtype of Number

    Among the lower bound wildcards, the wildcard " ? super Long "  denotes the family of types that are supertypes of Long , the type Long itself being included.  The wildcard " ? super Number "  denotes the family of types that are supertypes of Number , the type Number itself being included.  Number is a supertype of Long , and for this reason the type family " ? super Number " is smaller than the type family " ? super Long "; the latter includes type Long as member, while the former excludes it.  In other words, the super-sub type relationship between the lower bounds leads to the opposite relationship between the resulting type sets, namely  a sub-super set   relationship. 


    Multi-Level Wildcards

    Matters are more complicated when it comes to multi-level wildcards.  In principle, the rules outlined above are extended to multi-level wildcards in analogy.  However, the resulting super-subset relationships tend to be everything but intuitive to understand, so that in practice you will probably want to refrain from overly complex multi-level wildcards.  Nonetheless, we discuss in the following the rules for super-subset relationships among two-level wildcards. 

    For multi-level wildcards we apply the same rules as before. The only difference is that the bounds are wildcards instead of concrete types. As a result we do not consider type relationships among the bounds, but set relationships. 

    • A wildcard with an upper bound A denotes a superset of another wildcard with an upper bound B, if A denotes a super set of B.
    • A wildcard with a lower bound A denotes a superset of another wildcard with a lower bound B, if A denotes a sub set of B.
    The bounds A and B are wildcards and we can look up their super-subset relationships in the tables above, which leads us to the following tables for multi-level wildcards: 
     
      upper-upper bound wildcards upper-lower bound wildcards
    ? ?
    ? extends ParType< ? > ? extends ParType< ? >
    ? extends ParType < ? extends SuperType > ? extends ParType< ? super SubType >
    ? extends ParType < ? extends SubType > ? extends ParType< ? super SuperType >
    ? extends ParType< concrete type * >
    *either SubType or a subtype thereof 
    ? extends ParType < concrete type * >
    *either SuperType or a supertype thereof
    concrete type* < concrete type** >
    *either ParType or a subtype thereof
    **either SubType or a subtype thereof
    concrete type* < concrete type** >
    *either ParType or a subtype thereof
    **either SuperType or a supertype thereof
      lower-upper bound wildcards lower-lower bound wildcards
    ? super ParType < concrete type * >
    *either SubType or a subtype thereof
    ? super ParType < concrete type * >
    *either SuperType or a supertype thereof
    ? super ParType< ? extends SubType > ? super ParType< ? super SuperType >
    ? super ParType < ? extends SuperType > ? super ParType< ? super SubType >
    ? super ParType< ? > ? super ParType< ? >
    concrete type* <?>
    *either ParType or a supertype thereof
    concrete type* <?>
    *either ParType or a supertype thereof

    The rules look fairly complex, but basically it is a recursive process.  For instance: the type set denoted by " ? extends ParType <? extends SuperType> " is a superset of the type set denoted by " ? extends ParTyp e <? extends SubType > " because the upper bound " ? extends SuperType " is a superset of the upper bound " ? extends SubType ", and this is because the inner upper bound SuperType is a supertype of  the inner upper bound SubType .  In this recursive way, the super-subset relationships of multi-level wildcards can be made plausible.  Here are some concrete examples: 

    Examples: 
     
    upper-upper bound wildcards upper-lower bound wildcards
    ? ?
    ? extends List<?> ? extends List<?>
    ? extends List<? extends Serializable> ? extends List<? super Long>
    ? extends List<? extends Number> ? extends List<? super Number>
    ? extends List<Long> ? extends List<Serializable>
    ArrayList<Long> LinkedList<Serializable>
    lower-upper bound wildcards lower-lower bound wildcards
    ?
    ? super List<Long> ? super List<Object>
    ? super List<? extends Number> ? super List<? super Serializable>
    ? super List<? extends Serializable> ? super List<? super Number>
    ? super List<?> ? super List<?>
    Collection<?> Collection<?>

    LINK TO THIS Technicalities.FAQ208
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subtype relationships exist among instantiations of parameterized types?
    What is the raw type?
    What is a concrete instantiation?
    What is a wildcard instantiation?
    What is the unbounded wildcard instantiation?

    Does "extends" always mean "inheritance"?

    No. 
    extends is an overloaded keyword in the Java programming language.  It has different meanings, depending on the context in which it appears. The extends keyword can appear in four different locations: 
    • in the definition of a class
    • in the definition of an interface
    • in the definition of type parameter bounds
    • in the definition of wildcard bounds
    Below we discuss each of these cases in detail.  Basically it boils down to the observation that extends refers to more general super-subtype relationship, of which inheritance is a special case.  In conjunction with class and interface definitions extends means inheritance.  In conjunction with type parameter bounds and wildcard bounds extends it means either inheritance, or identity, or member of a type family denoted by a wildcard instantiation. 
     

    Definition of classes and interfaces

    Example ( extends in the definition of a class): 

    public class Quadruple<T> extends Triple<T> {
      private T fth;
      public Triple(T t1, T t2, T t3, T t4) {
        super(T1, t2, t3);
        fth = t4;
      }
      ...
    }
    This is an example where extends means inheritance. We define a subclass Quadruple that is derived from a superclass Triple .  This kind of inheritance exists between non-generic and generic classes. It leads to a super-subtype relationship between the two types.  In case of generic types it leads to a super-subtype relationship between instantiations of the two types that have identical type arguments.  For instance, Triple<Long> is a subtype of Triple<Long> , and Quadruple<? extends Number> is a subtype of Triple<? extends Number>

    Example ( extends in the definition of an interface): 

    public interface SortedSet<E> extends Set<E> {
      ...
    }
    This is another example where extends means inheritance. This time the inheritance relationship exists between two interfaces instead of two classes. We have the super-subtype relationships as for classes. 
     

    Definition of type parameter bounds

    Example ( extends in the definition of type parameter bounds): 

    public class Caller<V, T extends Callable<V>> {
        public Caller(T task) {
          FutureTask<V> future = new FutureTask<V>(task);
          Thread thread = new Thread(future);
          thread.setDaemon(false);
          thread.start();
          try { System.out.println ("result: " + future.get()); }
          catch (Exception e) { e.printStackTrace(); }
        }
    }
    In this example extends does not mean inheritance.  The extends keyword is here used to define the bounds of a type parameter.  A common misunderstanding is that the type argument that later replaces the type parameter in an instantiation must inherit from the bounds.  This is often the case, but it is not the only option. 

    In our example, we can supply a sub-interface of Callable<V> as a type argument, that is, an interface that extends the bound.  But we can also supply a class type that implements the bound.  In other words, extends in conjunction with type parameter bounds does not strictly mean inheritance, but it also includes the implements -relationship that exists between classes and interfaces. 

    In conjunction with type parameter bounds the extends keyword refers to an even broader notion of subtyping.  It includes relationships that cannot be expressed in terms of extends or implements as we know them from non-generic Java. Consider the following example. 

    Example ( extends in the definition of a type parameter bound that is a final class): 

    public class SomeClass<T extends String> {
      ...
    }
    In this example the bound is a final class.  Final classes cannot be inherited from.  The only permitted type argument is type String , which is not a type that inherits from the bound; it is the bound itself.   When applied to a bound that is a final class, extends does not mean inheritance; it means identity

    Let us consider another example that demonstrates that extends in conjunction with type parameter bounds means more than inheritance. 

    Example ( extends in the definition of a type parameter bound that is a wildcard parameterized type): 

    public class SomeClass<T extends Collection<?>> {
      ...
    }
    In this example the bound is a wildcard instantiation of the Collection interface. Wildcard parameterized types cannot be inherited from. In this case extends does not mean inheritance either. It refers to the super-subtype relationship that exists among wildcard parameterized types and concrete parameterized type.  Conceivable type arguments would be concrete parameterized type, such as Collection<String> or List<Long> ,  but also other wildcard parameterized types, such as Collection<? extends Number> .  These type arguments do not inherit from the bound, but they are members of the type family that the bound denotes. When applied to a bound that is a wildcard parameterized type, extends does not mean inheritance; it means member of the type family denoted by the wildcard parameterized type. 
     

    Definition of wildcard bounds

    Example ( extends in the definition of a wildcard bound): 

    List<? extends Number> ref = new ArrayList<Number>();
    The meaning of extends in conjunction with wildcard bounds is similar to the meaning of extends in conjuction with type parameter bounds.  It does NOT mean that the unknown type that the wildcard stands for (the so-called wildcard capture ) must inherit from the wildcard bound. It can, but it does not have to. The capture can equally well be the bound itself and extends would mean identity instead of inheritance. 

    If the bound is a wildcard parameterized type, then extends refers to the subtype relationship that exists among wildcard parameterized types and concrete parameterized types. 

    Example ( extends in the definition of a wildcard bound): 

    Triple<? extends Collection<?>> q = new Triple<List<? extends Number>>();
    In this example the wildcard capture cannot be a type that inherits from the bound, because wildcard parameterized types such as Collection<?> cannot be inherited from.  Instead the wildcard capture must be a member of the type family denoted by Collection<?> ,  such as Collection<String> , List<Number> , List<?> or List<? extends Number> .  Again, extends does not mean inheritance; it means member of the type family denoted by the wildcard parameterized type.
    LINK TO THIS Technicalities.FAQ209
    REFERENCES How do parameterized types fit into the Java type system?
    Which super-subset relationships exist among wildcards?
    What is the capture of a wildcard?

     

    Exception Handling

    Can I use generic or parameterized types in exception handling?

    No.  Exception and error types must not be generic.
    It is illegal to define generic types that are directly or indirectly derived from class Throwable . Consequently, no instantiations of generic type appear anywhere in exception handling.
    LINK TO THIS Technicalities.FAQ301
    REFERENCES Why are generic exception and error types illegal?

    Why are generic exception and error types illegal?

    Because the virtual machine cannot distinguish between different instantiations of a generic exception type.
    A generic class must not directly or indirectly be derived from class Throwable , which means that generic exception or error types are not allowed. Imagine if they were allowed ... 

    Example (of illegal generic exception type): 

    class IllegalArgumentException<T> extends Exception {   // illegal
      private T info;
      public IllegalArgumentException(T arg) { info = arg; }
      public T getInfo() { return info; }
    }
    We might then want to catch instantiations of this (illegal) generic exception type. 

    Example (of illegal  use of illegal parameterized exception type): 

    void method_1() {
      try { method_2(); }
      catch (IllegalArgumentException<String> e) { ... } // illegal
      catch (IllegalArgumentException<Long> e) { ... } // illegal
      catch (Throwable e) { ... }
    }
    Taking into account that generic Java source code is translated to Java byte code by type erasure, it should be clear that the method's catch clauses do not make any sense.  Both parameterized exception types have the same runtime type and the mechanism for catching exceptions is a runtime mechanism performed by the virtual machine based on the non-exact runtime types.  The JVM has no chance to distinguish between different instantiations of the same generic (exception) type.  For this reason, generic exception and error types are pointless in Java and banned from the language. (Note that generic exception and error types are not pointless per se, but in the context of Java generics with type erasure their are nonsensical.) 

    Other problems occur when we define methods that throw instantiations of an (illegal) generic exception type. 

    Example (of illegal  use of illegal parameterized exception type): 

    void method_1() 
      throws IllegalArgumentException<String>, IllegalArgumentException<Long> { // illegal
      ... do something ...
      throw new IllegalArgumentException<String>("argument missing");
      ... do something  else ...
      throw new IllegalArgumentException<Long>(timeout);
    }
    Again, after type erasure, both parameterized exception types have the same runtime type and the method's throws clause is nonsensical. The method could at best throw the raw type, which means that it must not create and throw any instantiations of the (illegal) generic type either.  Another reason to disallow generic exception and error types.
    LINK TO THIS Technicalities.FAQ302
    REFERENCES What is type erasure?

    Can I use a type parameter in exception handling?

    It depends. 
     Type parameters can appear in throws clauses, but not in catch clauses.
    LINK TO THIS Technicalities.FAQ303
    REFERENCES Can I use a type parameter in a catch clause?
    Can I use a type parameter in in a throws clause?
    Can I throw an object whose type is a type parameter?

    Can I use a type parameter in a catch clause?

    No.
    Using a type parameter in a catch clause is nonsensical because of the translation by type erasure.

    Example (before type erasure): 

    < E extends Exception > void someMethod() {
      try { &hellip; do something that might raise an exception &hellip;
      } catch ( E e) { &hellip; do something special for this particular exception type &hellip;
      } catch (IllegalStateException e) { &hellip; handle illegal state &hellip;
      } catch (Exception e) { &hellip; handle all remaining exceptions &hellip;
      }
    }
    Example (after type erasure): 
    void someMethod() {
      try { &hellip; do something that might raise an exception &hellip;
      } catch ( Exception e) { &hellip; do something special for this particular exception type &hellip;
      } catch (IllegalStateException e) { &hellip; handle illegal state &hellip;
      } catch (Exception e) { &hellip; handle all remaining exceptions &hellip;
      }
    }
    After type erasure the catch clause would boil down to a catch clause using the type parameter's bound.  This is because type parameters do not have a runtime type representation of themselves.  Type parameters are replaced by their leftmost bound in the course of translation by type erasure. In our example the catch clause for the unknown exception type E is translated by type erasure to a catch clause for type Exception , which is the bound of the type parameter E .  This catch clause for type Exception precedes further catch clauses for other exception types, and renders them pointless. 

    In other words, there never is a catch clause for the particular unknown exception type that the type argument stands for. Instead of catching a particular exception type we end up catching the bound of the unknown exception type, which changes the meaning of the sequence of catch clauses substantially and is almost always undesired.  For this reason, the use of type parameters in catch clauses is illegal.

    LINK TO THIS Technicalities.FAQ304
    REFERENCES Can I use a type parameter in in a throws clause?
    Can I throw an object whose type is a type parameter?

    Can I use a type parameter in in a throws clause?

    Yes.
    Using a type paramter in a throws clause is permitted. 

    Example (before type erasure): 

    public interface Action<E extends Exception> {
      void run() throws E ;
    }
    public final class Executor {
      public static <E extends Exception>
        void execute(Action<E> action) throws E
          &hellip;
          action.run();
          &hellip;
      }
    }
    public final class Test {
      private static class TestAction implements Action<java.io.FileNotFoundException> {
        public void run() throws java.io.FileNotFoundException {
          &hellip;
          throw new java.io.FileNotFoundException()
          &hellip;
      }
      public static void main(String[] args) {
        try { 
          Executor.execute(new TestAction()) ;
        } catch (java.io.FileNotFoundException f) { &hellip; }
      }
    In this example we see a generic interface Action whose type parameter E is the exception type that its run method throws.  This is perfectly reasonable, because throws clauses are a compile-time feature and the lack of a runtime type representation of the type parameter is not needed. At runtime, a particular exception type will have replaced the type parameter E , so that we would throw and catch an object of a concrete exception type.  In our example we instantiate the Action interface using the FileNotFound exception type as a type argument, so that a FileNotFound exception is raised and caught. 

    Even after type erasure the code snippet above still captures the intent. 

    Example (after type erasure): 

    public interface Action {
      void run() throws Exception ;
    }
    public final class Executor {
      public static void execute(Action action) throws Exception
          &hellip;
          action.run();
          &hellip;
      }
    }
    public final class Test {
      private static class TestAction implements Action {
        public void run() throws java.io.FileNotFoundException {
          &hellip;
          throw new java.io.FileNotFoundException()
          &hellip;
      }
      public static void main(String[] args) {
        try {
          Executor.execute(new TestAction()) ;
        } catch (java.io.FileNotFoundException f) { &hellip; }
      }
    LINK TO THIS Technicalities.FAQ305
    REFERENCES Can I use a type parameter in a catch clause?
    Can I throw an object whose type is a type parameter?

    Can I throw an object whose type is a type parameter?

    In principle, yes, but in practice, not really.
    We can declare methods that throw an exception (or error) of unknown type. 

    Example (of method with type parameter in throws clause): 

    interface Task< E extends Exception > {
      void run() throws E ;
    }
    Can such a method throw an object of the unknown exception (or error) type?  The method has in principle 3 ways of raising such an exception (or error): 
    • create a new exception (or error) and throw it
    • catch the exception (or error) of an invoked operation and re-throw it
    • propagate the exception (or error) of an invoked operation
    As we must not create objects of an unknown type the first possibility is not an option.  Since type parameters must not appear in catch clauses, we cannot catch and therefore not re-throw an exception of an unknown type.  At best, we can propagate an exception of unknown type that is raised by any of the invoked operations. 

    Example (throwing an object of unknown type): 

    final class CleanUp< E extends Exception , T extends Task<E>> {
      public void cleanup(T task) throws E {
        task.run();
      }
    }
    final class DisconnectTask implements Task<IllegalAccessException> {
      public void run() throws IllegalAccessException {
        ...
        throw new IllegalAccessException();
        ...
      }
    }
    class Test {
      public static void main(String[] args) {
        CleanUp<IllegalAccessException,DisconnectTask> cleaner 
           = new CleanUp<IllegalAccessException,DisconnectTask>();
        try { cleaner.cleanup(new DisconnectTask()); }
        catch (IllegalAccessException e) { e.printStackTrace(); }
      }
    }
    LINK TO THIS Technicalities.FAQ306
    REFERENCES Can I create an object whose type is a type parameter?
    Can I use a type parameter in a catch clause?
    Can I use a type parameter in in a throws clause?

     

    Static Context


     

    How do I refer to static members of a parameterized type?

    Using the raw type as the scope qualifier, instead of the any instantiation of the generic type.
    If you refer to a static member of a generic type, the static member name must be preceded by the name of the enclosing scope, such as EnclosingType.StaticMember .  In case of a generic enclosing type the question is: which instantiation of the generic type can or must be used as the scope qualifier? 

    The rule is that no instantiation can be used.  The scope is qualified using the raw type.  This is because there is only one instance of a static member per type. 

    Example (of a generic type with static members): 

    public final class Counted<T> {
      public  static final int MAX = 1024;
      public  static class BeyondThresholdException extends Exception {}

      private static int count;
      public  static int getCount() { return count; }

      private final T value;
      public Counted(T arg) throws BeyondThresholdException { 
        value = arg; 
        count++; 
        if (count >= 1024)  throw new BeyondThresholdException();
      }
      public void finalize() { count--; }
      public T getValue() { return value; }
    }


    int m = Counted .MAX;      // ok
    int k = Counted <Long> .MAX; // error
    int n = Counted <?> .MAX; // error

    try {
      Counted<?>[] array = null;
      array[0] = new Counted<Long>(10L);
      array[1] = new Counted<String>("abc");
    }
    catch ( Counted .BeyondThresholdException e) {
      e.printStackTrace();
    }
    System.out.println( Counted .getCount());   // ok
    System.out.println( Counted <Long> .getCount()); // error
    System.out.println( Counted <?> .getCount()); // error
     

    In the example above, the generic class Counted has a static member MAX and there is only one unique Counted.MAX , regardless of the number of objects of type Counted and regardless of the number of instantiations of the generic type Counted that may be used somewhere in the program. Referring to MAX as Counted<String>.MAX , Counted<Long>.MAX , Counted<?>.MAX , etc. would be misleading, because it suggests that there were several manifestations of the MAX member, which is not true.  There is only one Counted.MAX , and it must be referred to using the raw type Counted as the scope qualifier. The same is true for other static members such as static methods and static nested types.  The example illustrates that we must refer to the static method as Counted.getCount and to the static nested exception class as Counted.BeyondThresholdException

    In sum, it is illegal to refer to a static member using an instantiation of the generic enclosing type.  This is true for all categories of static members, including static fields, static methods, and static nested types, because each of these members exists only once per type.

    LINK TO THIS Technicalities.FAQ351
    REFERENCES Is there one instances of a static field per instantiation of a generic type?
    Why can't I use a type parameter in any static context of the generic class?
    How do I refer to an interface type nested into a generic type?
    How do I refer to an enum type nested into a generic type?
    How do I refer to a (non-static) inner class of a generic type?
    Can I import a particular instantiation of generic type?

    How do I refer to a (non-static) inner class of a generic type?

    Using an instantiation of the enclosing generic type as the scope qualifier, instead of the raw type.
    Static nested types are referred to using the raw form of the enclosing generic type as the scope qualifier.  This is different for inner classes. 

    Like a static nested type, an inner class exists only once, in the sense that there is only one .class file that represents the inner class.  Different from a static nested type, an inner class depends on the type argument of its outer class type.  This is because each object of an inner class type has a hidden reference to an object of the outer class type.  The type of this hidden reference is an instantiation of the generic enclosing type.  As a result, the inner class type is not independent of the enclosing class's type arguments. 

    Example (of an inner class nested into a generic outer class): 

     class Sequence <E> {
            private E[] theSequence;
            private int idx;

            // static classes
            public static class NoMoreElementsException extends Exception {}
            public static class NoElementsException extends Exception {} 

            // (non-static) inner class
            public class Iterator { 
                boolean hasNext() {
                    return (theSequence != null && idx < theSequence.length);
                }
               E getNext() throws NoElementsException, 
                                   NoMoreElementsException, 
                                   java.lang.IllegalStateException {
                    if (theSequence == null)
                        throw new NoElementsException();
                    if (idx < 0)
                        throw new java.lang.IllegalStateException();
                    if (idx >= theSequence.length)
                        throw new NoMoreElementsException();
                    else
                        return theSequence[idx++];
                }
            }
            public Iterator getIterator() {
                return this.new Iterator();
            }
    }

    class Test {
        private static <T> void print(Sequence<T> seq) 
          throws Sequence.NoElementsException
                 Sequence.NoMoreElementsException {
            Sequence <T> .Iterator iter = seq.new Iterator();
            while (iter.hasNext())
                System.out.println(iter.getNext()); 
        }
       public static void main(String[] args) {
            try {
                Sequence<String> seq1 = new Sequence<String>();
                ... fill the sequence ...
                print(seq1);
                Sequence<Long> seq2 = new Sequence<Long>();
                ... fill the sequence ...
                print(seq2);
            } catch (Exception e) { e.printStackTrace();
            }
        }
    }

    In the example above, the inner class Iterator depends on the outer class's type parameter E : the type parameter E is the return type of the iterator's getNext method and the inner class access the outer class's array of elements of type E .   For this reason, the iterator type is referred to as Sequence<T>.Iterator (using an instantiation), instead of just Sequence.Iterator (using the raw type).  This does not imply, that a scope qualification using the raw type is illegal; it is permitted and it means that the outer object being referred to by the inner object is of the raw type instead of a more specific type. 

    In contrast, the nested exception types are static classes and do not depend on the outer class's type parameter. (Static nested types never depend on their enclosing type's type parameters, because the type parameters must not appear in any static context of a generic class. Details are explained in a separate FAQ entry.) Static nested classes must be referred to using the raw type as the scope qualifier, that is, as Sequence.NoElementsException ;  use of an instantiation as the scope, such as Sequence<T>.NoElementsException , is illegal. 

    LINK TO THIS Technicalities.FAQ352
    REFERENCES How do I refer to static members of a generic type?
    Why can't I use a type parameter in any static context of the generic class?

    How do I refer to an interface type nested into a generic type?

    Using the raw type as the scope qualifier, instead of the any instantiation of the generic type.
    Nested interfaces are implicitly static. This is sometimes confusing because the interface looks like it were a non-static member of its enclosing class, while in fact it is static. As a static member of a generic type it must be referred to using the raw form of the enclosing type as the scope qualifier.  Using an instantiation as the scope qualifier is illegal and rejected by the compiler. 

    Example (of a nested interface): 

    class Controller <E extends Executor > {
      private E executor;
      public Controller(E e) { executor = e; }
      ... 
      public interface Command { void  doIt(Runnable task); } 

      public Command command() {
        return new Command() {
          public void  doIt(Runnable task) { executor.execute(task); }
        };
      }
    }
    class Test
      public static void test(Controller<ThreadPoolExecutor> c) {
        Controller<ExecutorService> controller 
          = new Controller<ExecutorService>(Executors.newCachedThreadPool());
        Controller.Command command = controller.command(); 
        ...
      }
    }

    The Command interface is nested into the generic Controller class.  The compiler does not allow that we refer to the nested interface using any instantiation of the enclosing generic class as the scope qualifier.  Instead of saying Controller<ExecutorService>.Command we must say Controller.Command

    Below is another example of a nested interface taken from the java.util package.  The generic Map interface has a nested Entry interface. 

    Example (of a nested interface taken from package java.util ): 

    public interface Map <K,V> {
      public interface Entry<K,V> {
        public K getKey();
        public V getValue();
        ...
      }
      public Set< Map.Entry<K, V> > entrySet();
      ...
    }
    The source code above is an excerpt from the JDK source code.  Note that the nested interface Entry is generic itself and has its own type parameters, which are independent of the outer interface's type parameters.  The fact that the type parameters of inner and outer interface have the same names, namely K and V , is perhaps confusing, but perfectly legal. The inner interface's type parameters K and V are visible only inside the inner interface and have nothing to do with the outer interface's type parameters K and V

    When the inner interface Entry is used it must be referred to using the raw type Map as the scope qualifier, that is, as Map.Entry<String,Long> for instance. A qualification such as  Map<String,Long>.Entry<String,Long> is illegal.

    LINK TO THIS Technicalities.FAQ353
    REFERENCES Why can't I use a type parameter in any static context of the generic class?
    How do I refer to static members of a parameterized type?
    Can I import a particular instantiation of parameterized type?

    How do I refer to an enum type nested into a generic type?

    Using the raw type as the scope qualifier, instead of the any instantiation of the generic type.
    Nested enum types are implicitly static. This is sometimes confusing because the enum type looks like it were a non-static member of its enclosing class, while in fact it is static. As a static member of a generic type it must be referred to using the raw form of the enclosing type as the scope qualifier.  Using an instantiation as the scope qualifier is illegal and rejected by the compiler. 

    Example (of a nested enum type): 

    class Controller <E extends Executor > {
      private State state;
      ... 
      public enum State { VALID, INVALID; } 
      public State getState() { return state; }
    }
    class Test
      public static void test(Controller<ThreadPoolExecutor> c) {
        Controller<ExecutorService> controller 
          = new Controller<ExecutorService>(Executors.newCachedThreadPool());
        Controller.State state = controller.getState();
        switch (state)) {
          case INVALID: ... ;
          case VALID:   ... ;
        } 
        ...
      }
    }
    The enum type  State is nested into the generic Controller class.  The compiler does not allow that we refer to the nested interface using any instantiation of the enclosing generic class as the scope qualifier.  Instead of saying Controller<ExecutorService>.State we must say Controller.State . The same applies to the enum constants; they are referred to as Controller.State.VALID and Controller.State.INVALID .
    LINK TO THIS Technicalities.FAQ354
    REFERENCES How do I refer to static members of a paramterized type?
    Can I import a particular parameterized type?

    Can I import a particular parameterized type?

    No. 
    In an import statement we must not use parameterized types; only raw types are permitted.  This applies to regular and static import statements. 

    Example (of a generic type with static members): 

    package com.sap.util;

    public final class Counted <T> {
      public  static final int MAX = 1024;
      public  static class BeyondThresholdException extends Exception {}

      private static int count;
      public  static int getCount() { return count; }

      private final T value;
      public Counted(T arg) throws BeyondThresholdException { 
        value = arg; 
        count++; 
        if (count >= 1024)  throw new BeyondThresholdException();
      }
      public void finalize() { count--; }
      public T getValue() { return value; }
    }



    import com.sap.util. * ;      // ok
    import com.sap.util. Counted ;     // ok
    import com.sap.util. Counted <String> ; // error

    import static com.sap. Counted . * ;   // ok
    import static com.sap. Counted <String> . * ; // error
    import static cam.sap. Counted .BeyondThresholdException; // ok
    import static com.sap. Counted <String> .BeyondThresholdException; // error

    LINK TO THIS Technicalities.FAQ355
    REFERENCES How do I refer to static members of a parameterized type?

    Why are generic enum types illegal?

    Because they do not make sense in Java.
    An enum type is similar to a class type of which only a limited number of instances, namely the enum values, exist. The enum values are static fields of the enum type. The key question is: of which type would the static enum values be if the enum type were allowed to be parameterized? 

    Example (of an illegal generic enum type): 

    public enum Tag<T> {  // illegal, but assume we could do this
      good, bad;

      private T attribute;
      public void setAttribute(T arg) { attribute = arg; }
      public T getAttribute() { return attribute; }
    }

    This enum type would be translated to a class that roughly looks like this: 
    public class Tag<T> extends Enum<Tag<T>> {
      public static final Tag< ??? > good;
      public static final Tag< ??? > bad;
      private static final Tag $VALUES[];
      private T attribute;

      private Tag(String s, int i) { super(s, i); }

      static {
        good   = new Tag("good", 0);
        bad    = new Tag("bad" , 1);
        $VALUES = (new Tag[] { good, bad });
      }

      public void setAttribute(T arg) { attribute = arg; }
      public T getAttribute() { return attribute; }
    }

    The static enum values cannot be of type Tag<T> because type parameters such a T must not appear in any static context. Should they be of the raw type Tag then?  In this case the private attribute field would be of type Object, the invocation of the setAttribute method would be flagged an "unchecked call" and the getAttribute method would only return Object . The entire parameterization would be pointless then. 

    On the other hand, if we wanted that the type of the enum values is a particular instantiation of the generic enum type, how would we tell the compiler?  There is no syntax for specifying the type of an enum value. 

    Also, when we refer to the enum values we must qualify their name by the name of their defining class, that is, Tag.good and Tag.bad .  Although Tag is a parameterized type, we cannot say Tag<String>.good or Tag<Long>.bad .  This is because static members of a generic type must be referred to via the raw type name.  In other words, we would not even be capable of expressing that we intend to refer to an enum value belonging to a particular instantiation of the generic enum type. 

    No matter how we put it: generic enum types do not make sense.

    LINK TO THIS Technicalities.FAQ356
    REFERENCES Why can't I use a type parameter in any static context of the generic class?
    How do I refer to static members of a parameterized type?

     

    Type Argument Inference


     

    What is type argument inference?

    The automatic deduction of the type arguments at compile time.
    Type inference happens when the compiler can deduce the type arguments of a generic type or method from context information.  In this case the type arguments need not be explicitly specified.

    There are two situations in which type inference is attempted:

    • when an object of a generic type is created , and
    • when a generic method is invoked.
    Example (of automatic type inference on instance creation): 
    class ArrayList<E> {
       ...
    }
    List<String> list1 = new ArrayList <String> ();  // type parameter specified     => E:=String
    List<String> list2 = new ArrayList <> ();        // type parameter inferred      => E:=String 
    List<String> list3 = new ArrayList();          // type parameter omitted       => using raw type
    Class ArrayList<E> is a generic class.  Usually you must specify the type parameter whenever you use the generic type (unless you want to use the raw type). In an instance creation expression you can omit the type parameter and replace it by empty angle brackets. When the compiler sees the empty angle brackets in the new -expression it takes a look at the lefthand side of the assignment in which the new -expression appears.  From the static type of the lefthand side variable the compiler infers the type parameter of the generic type of the newly created object. In the example above the compiler concludes that the type variable E must be replaced by the type String . If you neither specify the type parameter no use the empty angle brackets you refer to the raw type.

    [Note: Type inference for new -expressions was introduced in Java 7 and did not exist in Java 5 and 6.]

    Example (of automatic type inference on method invocation): 

    class Collections {
       ...
       public static <T> void copy(List<? super T> dest, List<? extends T> src) { ... }
       ...
    }

    List<String> src = new ArrayList<>();
    List<Object> dst = new ArrayList<>();

    Collections. <CharSequence> copy(dst,src);  // type parameter specified     => T:=CharSequence
    Collections. <> copy(dst,src);              // error: illegal syntax
    Collections.copy(dst,src);                // type parameter inferred      => T:=String

    The copy() method is a generic method.  When the generic method is invoked without explicit specification of the type argument then the compiler takes a look at the arguments that are provided for the method call.  From their static types the compiler infers the type parameter of the generic copy() method.  In the example above the compiler concludes that the type variable T must be replaced by the type String .  Different from type inference in conjunction with new-expressions empty angle bracket are not permitted; the brackets must be omitted entirely.
    LINK TO THIS Technicalities.FAQ400
    REFERENCES What is type argument inference for generic methods?
    What is type argument inference for instance creation expressions?
    What is the diamond operator?
    Is there a correspondence between type inference for method invocation and type inference for instance creation?

    Is there a correspondence between type inference for method invocation and type inference for instance creation?

    Yes, the instance creation expression for a generic type is treated like invocation of a generic creator method.
    The rules for type inference  for method invocation and type inference for instance creation are the same.  Consider a generic class with a constructor:
    class SomeClass<T> {
        SomeClass(T arg) { ... }
    }
    The creation of an object of this type can involve type inference, e.g. in this example:
    SomeClass<Long> ref = new SomeClass<>(0L);
    The type inference for the instance creation is performed in the same way as for a static creator method.   If the class had the following creator method:
    class SomeClass<T> {
        SomeClass(T arg) { ... }
        static <E> SomeClass<E> make(E arg) { return new SomeClass<E>(arg); }
    }
    then the type inference for the invocation of the creator method would yield the same result as type inference for the instance creation.  That is, the following leads to equivalent type inference:
    SomeClass<Long> ref = new SomeClass<>(0L);
    SomeClass<Long> ref = SomeClass.make(0L);
    LINK TO THIS Technicalities.FAQ400A
    REFERENCES What is type argument inference for instance creation expressions?
    What is type argument inference for generic methods?

    What is the "diamond" operator?

    It denotes the empty angle brackets that are used for type inference in new -expressions.
    Since Java 7 the compiler can infer the type parameters of a parameterized type in a new -expression.  In order to trigger the type inference the so-called diamond operator is used.  Below is an example.

    Example (of diamond operator): 

    List<String> list1 = new ArrayList <String> (); 
    List<String> list2 = new ArrayList <> (); 
    The empty angle brackets <> are called the diamond operator .  The diamond operator is not really an operator in the sense of the syntax specification of the Java programming language.  Rather it is just an empty type parameter specification.  The empty brackets are needed in order to distinguish between the raw type ArrayList and the incomplete type ArrayList<> .

    Until Java 9 the diamond operator was not permitted in anonymous inner class definitions.

    Here is an example:

    Callable<Long> task = new Callable <> () {        // error in Java 7/8; fine since Java 9
        public Long call() { return 0L; }
    };
    LINK TO THIS Technicalities.FAQ400B
    REFERENCES What is type argument inference for instance creation expressions?
    Why does the type inference for an instance creation expression fail?

    What is type argument inference for instance creation expressions?

    The automatic deduction of the type arguments in a new -expression.
    When an object of a parameterized type is created using a new -expression (also called an instance creation expression ) then the compiler can infer part of the type information of the object to be created. More specifically, the compiler can deduce the type parameters of the parameterized type if it is incomplete.  In order to trigger the automatic type inference the so-called diamond operator is used (see Technicalities.FAQ400A ). [Note: Type inference for new-expressions is available since Java 7.]

    Type inference takes into account the context in which the new -expression appears and what the new -expression looks like.  The type inference process works in two separate steps:

    • First, the compiler takes a look at the static types of the constructor arguments in the new -expression.
    • Second, if any of the missing type parameters cannot be resolved from the constructor arguments, then the compiler uses information from the context in which the new -expression appears.
    In Java 7, the only permitted inference context is an assignment context .  If the new -expression is the right-hand side of an assignment, then the compiler deduces the missing type parameter information from the lefthand side of the assignment, if possible.

    Since Java 8, an additional inference context is permitted, namely the method invocation context .  If the new -expression is the argument to a method invocation, then the compiler deduces the missing type parameter information from the method's declared argument type, if possible.

    Examples (of type inference for an  instance creation expression without constructor arguments): 

    List<String> list1 = new ArrayList <String> (); 
    List<String> list2 = new ArrayList <> ();        // type inference

    Map<Callable<String>, List<Future<String>>> tasks1 
    = new HashMap <Callable<String>, List<Future<String>>> (); 
    Map<Callable<String>, List<Future<String>>> tasks2 
    = new HashMap <> ();                             // type inference

    In the examples above no constructor arguments are specified.  As a result, the compiler cannot deduce any type information from the constructor arguments.  Instead it takes a look at the static type of the expression on the lefthand side of the assignment and infers the missing type parameters from there.

    Examples (of improved type inference in Java 8): 

    List<String> list1 = new ArrayList<> ();                                // fine since Java 7
    List<String> list2 = Collections.synchronizedList( new ArrayList<> () );  // error in Java 7 ; fine in Java 8


    error: incompatible types
            List<String> list3 = Collections.synchronizedList(new ArrayList<>()); 
                                                             ^
      required: List<String>
      found:    List<Object>
    In both examples type inference is needed, because no constructor arguments are specified.  The first new -expression appears in an assignment context and the compiler infers the missing type parameter String from the left-hand side of the assignment.  The second new -expression appears in a method invocation context.  Before Java 8, this yields a compile-time error. Since Java 8, the compiler infers the missing type parameter String from the declared type of the argument of the synchronizedList method. (Actually, it is a little more complicated.  The synchronizedList method is a generic method and the compiler must first infer the generic method's type parameter  before it knows the method's declared argument type.  The generic synchronizedList method appears in an assignement context, from which the compiler deduces that the type parameter for synchronizedList must be String . Its declared argument type then is List<String> and from this information the compiler infers that the new ArrayList must be an ArrayList<String> .)
     

    The inference is different if constructor arguments are provided.  In such a context the compiler takes a look at the static types of the constructor arguments and ignores the lefthand side of the assignment.

    Examples (of type inference for an  instance creation expression with constructor arguments): 

    Set<Long>   s1 = new HashSet<>();
    Set< Long >   s2 = new HashSet<>(Arrays.asList(0L,0L));
    Set< Number > s3 = new HashSet<>(Arrays.asList(0L,0L));   // error in Java 7 ; fine since Java 8
    Set<Number> s4 = new HashSet<Number>(Arrays.asList(0L,0L)); 


    error: incompatible types
            Set<Number> s3 = new HashSet<>(Arrays.asList(0L,0L)); 
                             ^
      required: Set<Number>
      found:    HashSet<Long>
    - The first new -expression does not have constructor arguments; the missing type parameter is inferred from the lefthand side of the assignment. The lefthand side is of type Set<Long> and compiler concludes that the missing type parameter must be Long .

    - The second new -expression has constructor arguments; the missing type parameter is inferred from the constructor argument. The constructor argument is of type List<Long> and the compiler again concludes that the missing type parameter must be Long .  Note, the lefthand side of the assignment is ignored because the constructor argument provides enough information for the type inference to complete successfully.

    - The third new -expression demonstrates that the lefthand side of the assignment is indeed ignored (in Java 7). The compiler again infers from the constructors argument, i.e., the result of the asList method, that the missing type parameter for the new HashSet must be Long .  This leads to a type mismatch and an according error message.  The compiler does not conclude that the missing type parameter should be Number because it ignores the lefthand side of the assignment.  In Java 8, the type inference was modified and improved.  Since then,  compiler infers Number as the type parameter form the new HashSet on the right-hand side of the compiler and from that deduces Number as the type parameter for the asList method.  In Java 8, this compiles just fine.

    - The fourth new -expression does not rely on type inference and simply specifies the intended type parameter explicitly.
     

    There is yet a different result of type inference if the context of the new -expression has neither constructor arguments nor a lefthand side of an assignment.  Here is an example.

    Examples (of type inference for an  instance creation expression in a method invocation context):

    void method(Set<Long> arg) { ... }

    method(new HashSet<>());                       // error in Java 7 ; fine in Java 8
    method(new HashSet<>(Arrays.asList(0L,1L,2L)));



    error: method method in class TypeInference cannot be applied to given types
            method(new HashSet<>()); 
            ^
      required: Set<Long>
      found: HashSet<Object>
    The new -expressions appears as the argument of a method invocation.  In the first invocation there is neither a constructor argument nor a lefthand side of an assignment.  For lack of more specific information the compiler in Java 7 concludes that the missing type parameter must be Object .  This leads to a type mismatch and an according error message.  This changed with Java 8.  The method invocation context is now a permitted type inference context. The compiler concludes from the declared argument type of method that the new HashSet must be a HashSet<Long> .
    The second invocation is fine because the compiler can infer the missing type parameter from the constructor argument.
    LINK TO THIS Technicalities.FAQ400C
    REFERENCES What is the diamond operator?
    Why does the type inference for an instance creation expression fail?

    Why does the type inference for an instance creation expression fail?

    Usually because there is not enough context information.
    Occasionally, the type inference for instance creation expressions yields results that are surprising at first sight and might lead to unexpected compile-time errors.  Here is an example.

    The result of type inference can be surprising for a new -expression that appears in a context other than an assignment. 

    Example (of surprising type inference): 

    String s = new ArrayList<>().iterator().next(); // error



    error: incompatible types: Object cannot be converted to String
            String s = new ArrayList<>().iterator().next();
                                                        ^
    In the example above an error message is issued because the new -expression new ArrayList <> () does not have constructor arguments and it neither appears on the right-hand side of an assignment nor as the argument of a method invocation.  Instead, it appears in a chain of method calls.  Such a chain is not a valid type inference context. 

    Hence the compiler has no information for type inference and concludes that the missing type parameter of the ArrayList is type Object . The iterator's next method then returns an Object instead of the expected String and the compiler accordingly reports a type mismatch.

    LINK TO THIS Technicalities.FAQ400D
    REFERENCES What is type argument inference for generic methods?
    What is type argument inference for instance creation expressions?
    Is there a correspondence between type inference for method invocation and type inference for instance creation?
    Why do temporary variables matter in case of invocation of generic methods?

     

    What is type argument inference for generic methods?

    The automatic deduction of the type arguments of a generic method at compile time.
    A generic method can be invoked in two ways: 
    • Explicit type argument specification .  The type arguments are explicitly specified in a type argument list.
    • Automatic type argument inference. The method is invoked like regular non-generic methods, that is, without specification of the type arguments.  In this case the compiler automatically infers the type arguments from the invocation context. 
    Example (of automatic type inference): 
    class Collections {
      public static <A extends Comparable<? super A>> A max (Collection<A> xs) {
        Iterator<A> xi = xs.iterator();
        A w = xi. next();
        while (xi.hasNext()) {
          A x = xi.next();
          if (w.compareTo(x) < 0) w = x;
        }
        return w;
      }

    final class Test {
      public static void main (String[ ] args) {
        LinkedList<Long> list = new LinkedList<Long>();
        list.add(0L); 
        list.add(1L);
        Long y = Collections.max(list) ;
      }
    }
    In this example, the max method is invoked like a regular method and the compiler automatically infers the type argument from the type of the method argument.  In our example the compiler finds that the formal method parameter is Collection<A> and that the actual method argument is of type LinkedList<Long> .  From this information the compiler concludes that A must be replaced by Long , which yields an applicable max method with the signature Long max(Collection<Long>) .
    LINK TO THIS Technicalities.FAQ401
    REFERENCES What is a parameterized or generic method?
    What is explicit type argument specification?
    What happens if a type parameter does not appear in the method parameter list?
    Why doesn't type argument inference fail when I provide inconsistent method arguments?

    What is explicit type argument specification?
     
    Providing a type argument list when the method is invoked.
    A generic method can be invoked with or without an explicit type argument specification. If you do not want to rely on the compiler's automatic type argument inference process you can specify the type arguments explicitly. 

    Example (of a generic method and its invocation): 

    public class Utilities {
      public static <T extends Comparable> T max(T arg1, T arg2) {
        return (arg1.compareTo(arg2)>0)?arg1:arg2;
      }
    }
    public class Test {
      public static void main(String[] args) {
        System.out.println(Utilities. <String>max ("abc","xyz")); 
      }
    }
    The max method can be invoked as Utilities.<String>max("abc","xyz") , where the type argument is explicitly provided, or as Utilities.max("abc","xyz") , in which case the compiler automatically infers the type argument. 

    The syntax for explicit type argument specification requires that the type argument list is precedes the method name, like in Utilities.<String>max .  Note the difference to parameterized types, where the type argument list follows the type name, like in List<String> .

    There is a little syntax quirk in the explicit type argument specification: it is required that the type argument(s) is preceded by either a type (for a static method like the one in the example), or the object on which the method is invoked (for a non-static method), or super (in case that a superclass's method is invoked).  This is even required when methods are invoked in the scope of the same class.  In the scope of the class we usually omit the type or object on which the method is invoked;  we simply say method() rather than this.method() .  This shorthand is not permitted when a type argument list precedes the method name. We must not say <String>method() , instead we must say this.<String>method()

    Example: 

    class SomeClass {
      private static <T> void parameterizedClassMethod()    { ... }
      private static     void regularClassMethod()          { ... }
      private        <T> void parameterizedInstanceMethod() { ... }
      private            void regularInstanceMethod()       { ... }

      public void anotherMethod() {
        ...
        regularClassMethod();                       // fine
        SomeClass.regularClassMethod();             // fine
        regularInstanceMethod();                    // fine
        this.regularInstanceMethod();               // fine

        <String> parameterizedClassMethod(); // error
        SomeClass. <String> parameterizedClassMethod (); // fine
        <String> parameterizedMethod(); // error
        this. <String> parameterizedMethod ();           // fine
        ...
      }
    }

    LINK TO THIS Technicalities.FAQ402
    REFERENCES What is a parameterized or generic method?
    How do I invoke a generic method?
    What is type argument inference?
    Can I use a wildcard as the explicit type argument of a generic method?

    Can I use a wildcard as the explicit type argument of a generic method?
     
    No, wildcards are not permitted as explicit type arguments of a generic method.
    When a generic method is invoked, then we usually rely on the compiler to infer the type argument of the generic method.  In rare cases, we specify the type argument explicitly.  Here is an example where explicit type argument specification would make sense.

    Example (of generic methods):

    class Factory { 
        private static Class< ? > type;

        public static <T> void setComponentType(Class< ? extends T> token) {
            type = token;
        }
        public static <T> List<T> make(int size) {
            Object array = Array.newInstance(type, size);
            return Arrays.asList((T[])array);    // warning: unchecked cast
        }
    }

    This class hat two factory methods that create a list which is backed by an array.  Such a list has a fixed size and is type-safe in the sense that it rejects elements of an undesired type, just like an array would reject elements of a type that is not compatible to the array's component type.

    Example (of using the factory methods):

    public static void main(String[] args) {
        Factory.setComponentType(String.class);

        List<String>  stringList; 
        stringList = Factory.make(10);
        stringList.set(0,"Hello");
        stringList.set(1,new Date());  // expected error: illegal argument type

        List<Date>  objectList;
        dateList = Factory.make(10);    // compiles although it should not !!!
        dateList.set(1,new Date());    // run-time error: ArrayStoreException
    }

    The factory is configured (using the setComponentType() method) to create lists that are backed by an array of strings.  When we invoke a factory method then the compiler performs type inference and tries to figure out what the best type argument for invocation of the generic make() method would be.  Since the type parameter does not appear in the method's arguments list the compiler infers the type argument from the context in which the return value is used. 

    As long as we assign the result of invoking the make() method to a reference of type List<String> , all is fine.  The compiler infers T:=String when the make() method is invoked. We can place strings into the list, but no other type of object, because the reference of type List<String> will not permit it.

    If we try assigning the result of invoking the make() method to a reference of type List<Date> , it will compile as well. The compiler will again infer the type argument from the usage of the return value; this time it infers T:=Date . However, when we attempt placing a date into the list, which is backed by a string array internally, an ArrayStoreException will be raised.  Basically, what we created is a list that will always raise ArrayStoreException s. This undesired situation is a side effect of the "unchecked cast" warning in the implementation of the make() method.

    In order to prevent the undesired situation, the make() method is best invoked with an explicitly specified type argument.

    Example (of explicit type argument specification):

    public static void main(String[] args) {
        Factory.setComponentType(String.class);

        List<String>  stringList; 
        stringList = Factory. <String> make(10); 
        stringList.set(0,"Hello");

        List<Date>  objectList;
        dateList = Factory. <String> make(10); // does no longer compile
        dateList.set(1,new Date());  // run-time error: ArrayStoreException
    }

    Basically, the example shows a situation in which explicit type argument specification serves a purpose and is helpful.

    In the example we have been using a concrete type when we specified the type argument explicitly, which raises the question: can we also use wildcards as explicit type arguments? The answer is: No, wildcards are not permitted as explicit type arguments of parameterized method. 

    Example (of a wildcard as explicitly specified type arguments of generic methods):

    List<? super String> list1 = Factory.make(10);                 // fine
    List<? super String> list2 = Factory.<String>make(10);         // fine
    List<? super String> list3 = Factory.< ? super String >make(10); // error
    The Java syntax simply does not allow wildcards in the location where explicit type arguments appear and you might see funny compiler message ranging from "wildcard is not allowed in this location" to less helpful statements such as "illegal start of type", "illegal start of expression", "( expected", "; expected" or the like.
    LINK TO THIS Technicalities.FAQ402A
    REFERENCES What is type argument inference?
    What is explicit type argument specification?
    What happens if a type parameter does not appear in the method parameter list?

    What happens if a type parameter does not appear in the method parameter list?
     
    The compiler tries to infer the type argument from the calling context.
    If the type parameter does not appear in the types of the method arguments, then the compiler cannot infer the type arguments by examining the types of the actual method arguments.  If the type parameter appears in the method's return type, then the compiler takes a look at the context in which the return value is used.  If the method call appears as the righthand side operand of an assignment, then the compiler tries to infer the method's type arguments from the static type of the lefthand side operand of the assignment. 

    Example (for inference from assignment context): 

    public final class Utilities {
      ...
      public static <T> HashSet<T> create(int size) { 
        return new HashSet<T>(size); 
      }
    }
    public final class Test
      public static void main(String[] args) {
        HashSet<Integer> hi = Utilities.create(10);
      }
    }
    The create method is generic and the type parameter T does not appear in the method parameter list; it appears in the method's return type HashSet<T> though.  The result of the method is assigned to a variable of type HashSet<Integer> so that the compiler infers that the type argument of the create method must be T:=Integer .  The compiler is even smart enough to infer the type argument of the create method if the method result is assigned to a variable of a supertype of HashSet<Integer> , such as Collection<Integer>

    The invocation of a generic method might appear as the argument of another method invocation.  Such an invocation context was not considered for type inference before Java 8.  This changed with the improved type inference in Java 8.

    In Java 5, 6, and 7, the compiler does not try to perform any special type inference when the invocation of a generic method appears in a method invocation context.  Instead the compiler handles the method call as though it would appear in no context. No context means that the compiler performs the type inference algorithm as though the method result was assigned to a variable of type Object

    Example (for inference from a method invocation context): 

    public final class Utilities {
      ...
      public static <T> HashSet<T> create(int size) {
        return new HashSet<T>(size);
      }
      public static void print( HashSet<String> h) { 
        for (String s : h) System.out.println(s);
      }
    }
    public final class Test
      public static void main(String[] args) {
        Utilities.print(Utilities.create(10));    // error in Java 5,6,7 ; fine in Java 8
      }
    }


    error: print(java.util.HashSet<java.lang.String>) cannot be applied to (java.util.HashSet<java.lang.Object>)
            Utilities.print(Utilities.create(10));
            ^
    In Java 5, 6, and 7,  the compiler treats the call Utilities.print(Utilities.create(10)) like it were an assignment Object o = Utilities.create(10)) .  A lefthand side of type Object does not provide any particular type information so that the compiler cannot really infer anything.  If no specific type can be inferred then the compiler chooses Object as the type argument.  With type Object as the type argument the create method returns a  HashSet<Object> , which is incompatible to a HashSet<String> and leads to the error message displayed above. 
    In Java 8, the compiler considers that the print method needs an argument of type HashSet<String> and figures out that the type parameter for the create method must be String then. 

    The key difference is that previously the method invocation context was treated like no context for type inference and in Java 8 it a valid type inference context, from which the compiler retrieves information for the type deduction process.

    If the type argument inference does not lead to the desired result or if we want to disable the automatic inference, we can explicitly specify the type arguments. 

    Example (for explicit type argument specification): 

    public final class Utilities {
      ...
      public static < T> HashSet<T> create(int size) { 
        return new HashSet<T>(size); 
      }
      public static void print(HashSet<String> h) {
        for (String s : h) System.out.println(s);
      }
    }
    public final class Test
      public static void main(String[] args) {
        Utilities.print(Utilities. <String> create(10));
      }
    }
    LINK TO THIS Technicalities.FAQ403
    REFERENCES What is a parameterized or generic method?
    What is type argument inference?
    What is explicit type argument specification?
    Why doesn't type argument inference fail when I provide inconsistent method arguments?
    Why do temporary variables matter in case of invocation of generic methods?

    Why doesn't type argument inference fail when I provide inconsistent method arguments?

    Because the "inconsistent" arguments might make sense to the compiler.
    Occasionally the compiler infers a type where we might expect that no type can be inferred. 

    Example (of surprising type argument inference): 

    public final class Utilities {
      ...
      public static <T> void fill( T [] array, T elem) {
        for (int i=0; i<array.length; ++i) { array[i] = elem; }
      }
    }

    public final class Test {
      public static void main(String[] args) {
        Utilities.fill(new String [5], new String ("XYZ"));  // T:=String
        Utilities.fill(new String [5], new Integer (100));   // T:=Object&Serializable&Comparable
      }
    }

    This is the example of a method whose type argument appears in several method arguments.  Quite obviously the intent is that the component type of the array should match the type of the second argument.  For this reason we might expect that a method invocation such as Utilities.fill (new String[5], new Integer(1 00)) would fail, because the argument types String[] and Integer are inconsistent. 

    However, the compiler does not reject this method call.  Instead it performs type inference and infers the common supertypes of String and Integer as type argument.  To be precise the compiler infers 

    T := Object & Serializable & Comparable<? extends Object&Serializable&Comparable<?>>
    which is a synthetic type construct used internally by the compiler.   It denotes the set of supertypes of String and Integer

    Whether the result of this successful type inference is desired or not depends on the circumstances.  In this example the source code compiles, but the method invocation in question will fail at runtime with an ArrayStoreException , because the method would try to store integers in an array of strings. 

    In Java 5, 6, and 7 it was possible to prevent the perhaps undesired type argument inference by a minor modification of the fill method. 

    Example (modified, in Java 5, 6, and 7): 

    public final class Utilities {
      ...
      public static < T , S extends T > void fill( T [] array, S elem) { 
        for (int i=0; i<array.length; ++i) { array[i] = elem; }
      }
    }

    public final class Test {
      public static void main(String[] args) {
        Utilities.fill(new String [5], new String ("XYZ"));  // T:=String and S:=String
        Utilities.fill(new String [5], new Integer (100));   // T:=String and S:=Integer => error (in Java 5,6,7)
      }
    }

    In Java 5, 6, and 7 the compiler  inferred both type arguments separately as String and Integer . When it checked the bounds it found that S is not within bounds because Integer is not a subtype of String and the call was rejected.

    Since Java 8 the compiler does no longer issue an error message and you will observe the same behavior as in the initial example without the additional type variable " S extends T ".  The fact that the type inference process  in Java 5, 6, and 7 could not find a common super type and issued an error message was just an accident.  The glitch was fixed in Java 8 and nowadays the compiler exploits the covariance of arrays in this example, too. 

    Example (same as above, but in Java 8): 

    public final class Utilities {
      ...
      public static < T , S extends T > void fill( T [] array, S elem) { 
        for (int i=0; i<array.length; ++i) { array[i] = elem; }
      }
    }

    public final class Test {
      public static void main(String[] args) {
        Utilities.fill(new String [5], new String ("XYZ"));  // T:=Object&Serializable&Comparable and S:=String  => fine
        Utilities.fill(new String [5], new Integer (100));   // T:=Object&Serializable&Comparable and S:=Integer => fine (in Java 8)
      }
    }

    LINK TO THIS Technicalities.FAQ404
    REFERENCES What is a parameterized or generic method?
    What is type argument inference?
    What is explicit type argument specification?
    What happens if a type parameter does not appear in the method parameter list?
    Why do temporary variables matter in case of invocation of generic methods?

    Why do temporary variables matter in case of invocation of generic methods?

    Because of the automatic type argument inference.
    Usually, it does not make a difference whether we use the result of a method call for invocation of the next method, like in 
    f(x).g();
    or whether we store the result first in a temporary variable and then pass the temporary variable to the next method, like in 
    tmp=f(x); 
    tmp.g();
    The effect is usually the same.  However, when the methods are generic methods, it may well make a difference.

    Example:

    public final class Utilities {
      ...
      public static <T> HashSet<T> create(int size) {
        return new HashSet<T>(size);
      }
    }
    Let us consider a chained method call where the result of the create method is used for calling the iterator method.  We can perform the chained method call in two steps using a temporary variable:
    HashSet<Integer>  tmp   = Utilities.create(5);
    Iterator<Integer> iter = tmp .iterator();
    Or we can perform it one step:
    Iterator<Integer> iter = Utilities.create(5).iterator();
    If the methods were non-generic methods the result of both invocation techniques would be the same. Not so in our example, where the first method is generic and the compiler must  infer the type parameter from the context.  Obviously, the context is different in a chained call compared to the use of temporaries. 

    In the two-step invocation the result of the create method appears in an assignment, and assignment is a context that the compiler considers for type inference. In the one-step invocation the result of the create method is used to invoke another method, and method chains are not considered for type inference. 

    Here is what the compiler infers for the two-step call:

    HashSet<Integer>  tmp   = Utilities.create(5);               // T:=Integer
    Iterator<Integer> iter = tmp .iterator();                   // T:=Integer
    For inference of the type argument of the create method the compiler takes a look at the type of the left-hand side of the assignement, namely the type of the temporary variable.  It is of type HashSet<Integer> and the compiler infers T:=Integer .

    The one-step call, in contrast, does not compile because the type argument inference works differently in this case:

    Iterator<Integer> iter = Utilities.create(5).iterator();


    error: incompatible types
            Iterator<Integer> iter = Utilities.create(5).iterator();
                                                                 ^
      required: Iterator<Integer>
      found:    Iterator<Object>
    For inference of the type argument of the create method the compiler does not consider any context information, because it neither appears in an assignment nor a method invocation context, but in a method chain instead.  It treats the invocation of create as though the result of create were assigned to a variable of type Object , which does not provide any type information to deduce anything from.  For this reason the compiler infers T:=Object , which yields an instantiation of the create method with the signature HashSet<Object> create() .
    Equipped with this information the compiler finds that the iterator method return an Iterator<Object> , which leads to the error message.

    The example demonstrates, that in rare cases there can be a difference between a one-step nested method call such as f(x).g(); and a two-step call using a temporary variable such as tmp=f(x); tmp.g(); . The difference stems from the fact that an assignment context is considered for the type argument inference, while other situations are not.
     

    LINK TO THIS Technicalities.FAQ405
    REFERENCES What is a parameterized or generic)method?
    What is type argument inference?
    What is explicit type argument specification?
    What happens if a type parameter does not appear in the method parameter list?
    Why doesn't type argument inference fail when I provide inconsistent method arguments?

     
     

    Wildcard Capture

    What is the capture of a wildcard?

    An anonymous type variable that represents the particular unknown type that the wildcard stands for.  The compiler uses the capture internally for evaluation of expressions and the term "capture of ?" occasionally shows up in error message.
    A wildcard is compatible with all types from a set of types. For instance, all instantiations of the generic type List , such as List<String> , List<Number> , List<Long> , etc. can be assigned to a reference variable of type List<?> .  Wildcards are typically used as argument or return types in method signatures. The goal and effect is that the method accepts arguments of a larger set of types, namely all types that belong to the type family that the wildcard denotes. 

    Example (of a wildcard in a method signature): 

    public static void reverse(List<?> list) {
      // ...  the implementation ...
    }
    The reverse method accepts arguments that are of a type that is an instantiation of the generic type List . In order to use the type argument list of type List<?> the compiler converts the wildcard instantiation to the so-called capture of the wildcard. The capture represents the particular albeit unknown type of the argument that is actually passed the method.  This particular unknown type is, of course, a member of the type family that the wildcard denotes. 

    The wildcard capture can be imagined as an anonymous type variable that the compiler generates internally and uses as the static type of the method parameter.  A type variable is like a type parameter of a generic type or method; it stands for a particular unknown type. Changing the method parameter's type from the instantiation using a wildcard to an instantiation using the capture is known as capture conversion . The translation of our method can be imagined as though the compiler had re-implemented the method to use a synthetic generic method that has the wildcard capture as it type parameter. 

    Example (pseudo code showing the wildcard capture): 

    private static <T_?001> void reverse_?001(List<T_?001> list) {
      // ...  the implementation ...
    }
    public static void reverse(List<?> list) {
      reverse_?001(list);
    }
    For the analysis and translation of the implementation of the reverse method the compiler will use List<T_?001> as the type of the method parameter. The synthetic type variable T_?001 is used for all purposes where the method parameter's static type information is needed, like for instance, in type checks and for type inference. 

    For illustration, let us consider a conceivable implementation of the reverse method using a generic helper method rev for which the compiler must infer the type arguments from the wildcard. 

    Example (implementation of the reverse method): 

    private static <T> void rev(List<T> list) {
      ListIterator<T> fwd = list.listIterator();
      ListIterator<T> rev = list.listIterator(list.size());
      for (int i = 0, mid = list.size() >> 1; i < mid; i++) {
        T tmp = fwd.next();
        fwd.set(rev.previous());
        rev.set(tmp);
      }
    }
    public static void reverse(List<?> list) {
      rev(list);
    }
    The compiler applies capture conversion and generates an anonymous type variable. In principle, the compiler translates the reverse method to something like this. 

    Example (pseudo code showing the wildcard capture): 

    private static <T> void rev(List<T> list) {
      ListIterator<T> fwd = list.listIterator();
      ListIterator<T> rev = list.listIterator(list.size());
      for (int i = 0, mid = list.size() >> 1; i < mid; i++) {
        T tmp = fwd.next();
        fwd.set(rev.previous());
        rev.set(tmp);
      }
    }
    private static <T_?001> void reverse_?001(List<T_?001> list) {
      rev(list);
    }
    public static void reverse(List<?> list) {
      reverse_?001(list);
    }
    Among other things, the compiler uses the wildcard capture T_?001 for  inference of the type argument T of the generic helper method rev . It infers T:=T_?001 and therefore invokes the instantiation <T_?001>rev of method rev
    LINK TO THIS Technicalities.FAQ501
    REFERENCES What is a wildcard capture assignment-compatible to?

    What is the capture of an unbounded wildcard compatible to?

    Nothing, except the unbounded wildcard itself. 
    The capture of a wildcard is compatible to a corresponding wildcard, never to a concrete type. 

    Example (implementation of assignment of wildcard instantiation): 

    private static void method( List<?> list) {
      List <String>            ll1 = list;     // error
      List <? extends String> ll2 = list;     // error
      List <? super String>    ll3 = list;     // error
      List <?>                 ll4 = list;     // fine
    }

    error: incompatible types
    found   : java.util.List <capture of ? >
    required: java.util.List<java.lang.String>
            List<String> ll1 = list;
                               ^
    error : incompatible types
    found   : java.util.List
    <capture of ?
    required: java.util.List<? extends java.lang.String>
            List<? extends String> ll2 = list;
                                         ^
    error : incompatible types
    found   : java.util.List
    <capture of ?
    required: java.util.List<? super java.lang.String>
            List<? super String> ll3 = list;
                                       ^
    The method takes an argument of type List<?> , which the compiler translates to type List<capture of ?> . The wildcard capture denotes a particular unknown type.  From the static type information "capture of ?" the compiler cannot tell, whether capture stands for String ; the capture could stand for any type.  On this ground the compiler rejects the assignment of the method result of type List<capture of ?> to the variable of type List<String> in the example. 
    LINK TO THIS Technicalities.FAQ502
    REFERENCES What is the capture of a wildcard?
    What does type-safety mean?

    Is the capture of a bounded wildcard compatible to the bound?

    No, not even if the bound is a final class. 
    The capture of a wildcard is compatible to a corresponding wildcard, never to a concrete type. Correspondingly, the capture of a bounded wildcard is compatible solely to other wildcards, but never to the bound. 

    For illustration we use the getClass method, which is defined in class Object (see java.lang.Object.getClass ). The result of the getClass method is of type Class<? extends X> , where X is the erasure of the static type of the expression on which getClass is called. 

    Example (with bounded wildcard):

    Number n = new Integer(5);
    Class<Number> c = n.getClass();  // error


    error: incompatible types
    found   : java.lang.Class<capture of ? extends java.lang.Number>
    required: java.lang.Class<java.lang.Number>
            Class<Number> c = n.getClass(); 
                                        ^
    In our example the static type of the expression on which getClass is called is Number .  Hence the return value is of type Class<capture of ? extends Number> . A variable of type Class<capture of ? extends Number> can refer to a Class<Number> , a Class<Long> , a Class<Integer> , etc.   There's no guarantee that is actually refers to a Class<Number> , and indeed, in our example it refers to a Class<Integer> . The compiler rightly complains.  How do we fix it? 

    Example (corrected): 

    Number n = new Integer(5);
    Class<?>                c1 = n.getClass(); 
    Class<? extends Number> c2 = n.getClass();
    Since getClass returns a wildcard instantiation we must assign the result to a wildcard instantiation.  Class<?> would be correct, but also the more specific type Class<? extends Number> would work. 

    Interestingly, the capture of a bounded wildcard, whose upper bound is a final class, is still incompatible to the bounds type, although the set of types that the bounded wildcard denotes contains only one type, namely the bounds type itself. 

    Example (using final class as bound): 

    String s = new String("abc");
    Class<String>           c0 = s.getClass();  // error
    Class<?>                c1 = s.getClass();  // fine
    Class<? extends String> c2 = s.getClass();  // fine


    error: incompatible types
    found   : java.lang.Class<capture of ? extends java.lang.String>
    required: java.lang.Class<java.lang.String>
            Class<String>           c0 = s.getClass(); 
                                                   ^
    LINK TO THIS Technicalities.FAQ503
    REFERENCES What is the capture of a wildcard?
    What is a wildcard capture assignment-compatible to?

     
     

    Wildcard Instantiations

    Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?

    It depends on the kind of wildcard.
    Using an object through a reference variable of a wildcard parameterized type is restricted. Consider the following class: 

    Example ( of a parameterized class): 

    class Box<T> {
      private T t;
      public Box(T t) { this.t = t; }
      public void put(T t) { this.t = t;}
      public T take() { return t; }
      public boolean equalTo(Box<T> other) { return this.t.equals(other.t); }
      public Box<T> copy() { return new Box<T>(t); }
    }
    In a wildcard parameterized type such as Box<?> the type of the field and the argument and the return types of the methods would be unknown.  It is like the field t would be of type " ? " and the put method would take an argument of type " ? " and so on.  In this situation the compiler does not let us assign anything to the field or pass anything to the put method. The reason is that the compiler cannot make sure that the object that we are trying to assign to the field or pass as an argument to a method is of the expected type, since the expected type is unknown.  Similar effects can be observed for methods such as like equalTo and clone , which  have a parameterized argument or return type and the type parameter T appears as type argument of the parameterized argument or return type. 

    Below is a table that lists which uses of fields and methods are legal or illegal. It assumes a class like this: 

    class X< T > {
      private T t;

      public  T     m()                   { ... }
      public  void m( T arg)              { ... }

      public  Y< T > f()                   { ... }
      public  void f(Y< T > arg)           { ... }

      public  Y<? extends T > f()         { ... }
      public  void f(Y<? extends T > arg) { ... }

      public  Y<? super T > f()           { ... }
      public  void f(Y<? super T > arg)   { ... }
    }

    Examples and further explanations can be found in subsequent FAQ entries. 
     
    X<?> unbounded wildcard
    legal illegal
    fields x = t We can read a field whose type is the type parameter. 
    The field is accessible through a reference of type Object .
    t = x We cannot assign to a field whose type is the type parameter 
    except: null
    methods T m() We can call methods that use the type parameter as the return type
    The returned value is accessible through a reference of type Object .
    void m( T ) We cannot call methods that use the type parameter as an argument type
    except: null
    Y< T > f()
    Y<? extends T > f()
    Y<? super T > f()
    We can call methods that use the type parameter as type argument in the return type or as an upper or lower wildcard bound in the return type
    The returned value is accessible through the unbounded wildcard instantiation of the return type (i.e. Y<?> ).
    void f( Y< T > )
    void f( Y<? extends T > )
    We cannot call methods that use the type parameter as type argument in an argument type or as an upper wildcard bound   in an argument type
    except: null
    void f( Y<? super T > ) We can call methods that use the type parameter as a lower wildcard bound   in an argument type
    The method argument must be either null or of type Y<Object> (the argument type instantiated for type Object ).
    X<? extends B> wildcard with upper bound
    legal illegal
    fields x = t We can read a field whose type is the type parameter.
    The field is accessible through a a reference whose type is the upper bound.
    t = x We cannot assign to a field whose type is the type parameter. 
    except: null
    methods T m() We can call methods that use the type parameter as the return type
    The returned value is accessible through a reference whose type is the upper bound.
    void m( T ) We cannot call methods that use the type parameter as an argument type
    except: null
    Y< T > f()
    Y<? extends T > f()
    We can call methods that use the type parameter as type argument in the return type or as an upper wildcard bound in the return type
    The returned value is accessible through the upper bound wildcard instantiation of the return type (i.e. Y<? extends B> ).
    void f( Y< T > )
    void f( Y<? extends T > )
    We cannot call methods that use the type parameter as type argument in an argument type or as an upper wildcard bound   in an argument type
    except: null
    Y<? super T > f() We can call methods that use the type parameter as an lower wildcard bound in the return type
    The returned value is accessible through the unbounded wildcard instantiation of the return type (i.e. Y<?> ).
    void f( Y<? super T > ) We cannot call methods that use the type parameter  as an lower wildcard bound in an argument type
    The method argument must be either null or of a type that belongs to the family denoted by Y<? super B> .
    X<? super B> wildcard with lower bound
    legal illegal
    fields t = x We can assign to a field whose type is the type parameter. 
    The value to be assigend must be either null or of a type that is the lower bound or a subtype thereof.
    x = t We can read a field whose type is the type parameter. 
    The field is accessible through a reference of type Object .
    methods void m( T ) We can call methods that use the type parameter as an argument type
    The method argument must be either null or of a type B (the lower bound). 
    T m() We can call methods that use the type parameter as the return type
    The returned value is accessible through a reference of type Object .
    Y< T > f()
    Y<? super T > f()
    We can call methods that use the type parameter as type argument in the return type or as a lower wildcard bound in  the return type
    The returned value is accessible through the lower bound wildcard instantiation of the return type (i.e. Y<? super B> ).
    void f( Y< T > ) We cannot call methods that use the type parameter as type argument in an argument type
    except: null
    Y<? extends T > f() We can call methods that use the type parameter as an upper wildcard bound in the return type .
    The returned value is accessible through the unbounded wildcard instantiation of the return type (i.e. Y<?> ).
    void f( Y<? extends T > ) We can call methods that use the type parameter  as an upper wildcard bound in an argument type
    The method argument must be either null or of a type that belong to the family denoted by Y<? extends B> .
    void f(Y<? super T >) We can call methods that use the type parameter as a lower wildcard bound   in an argument type
    The method argument must be either null or of type Y<Object> (the argument type instantiated for type Object ).
    LINK TO THIS Technicalities.FAQ601
    REFERENCES What is a wildcard instantiation?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard parameterized type, can I read and write fields whose type is the type parameter?

    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?

    We cannot call methods through an unbounded wildcard parameterized type that take arguments of the "unknown" type.  But we can call methods that return objects of the "unknown" type.
    Example: 
    class Box< T > {
      private T t; 

      public Box(T t) { this.t = t; }
      public void put( T t) { this.t = t;}
      public T take() { return t; }

      public boolean contains( T t) { return this.t == t; }
      public String toString() { return "Box["+t.toString()+"]"; }
    }
    class Test {
      public static void main(String[] args) {
        Box<?> box = new Box<String>("abc");

        box.put("xyz");     // error
        box.put(null);     // ok

        box.contains("abc");    // error
        box.toString(); // ok

        String s = box.take();  // error
        Object o = box.take();  // ok
      }
    }

    We cannot call the put method of the Box type through a reference variable of type Box<?> , because the method takes an argument of the unknown type that the wildcard stands for.  From the type information Box<?> the compiler does not know whether the object we are passing to the method is compatible with the actual object contained in the box.  If the Box<?> would be refering to a Box<Long> , then it would clearly violate the type guarantees if we could put a string into the box that is supposed to contain a long value. The only argument that is accepted it the null reference, because it has no type. 

    The same reasoning applies to all methods that take an argument of the "unknown" type, even if the method does not even modify the box, like the contains method.  It just takes an object of the "unknown" type and compares it.  If a string is passed to the contains method of a box that contains a long value, it simply returns false .  No harm is done.  Yet the invocation is illegal if performed through a reference variable of type Box<?> . [Defining the contains method as taking an argument of type Object , instead of T , would avoid this effect.  In this case the contains method would not take an object of "unknown", but an object of "any" type, and it would be permitted to invoke it through a reference variable of type Box<?> .]

    We can freely invoke any methods that neither take nor return objects of the "unknown" type. 

    The example demonstrates that methods returning an object of the unknown type can be called and return an object of unknown type, which can be assigned to a reference variable of type Object , but to not to a reference variable of a more specific type.

    LINK TO THIS Technicalities.FAQ602
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard instantiation, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?

    We cannot call methods through an unbounded wildcard parameterized type that take arguments of the "unknown" type.  But we can call methods that return objects of the "unknown" type.
    The rules for an upper bound wildcard parameterized type are the same as for an unbounded wildcard parameterized type.  The only difference that a returned object of "unknown" type is known to be compatible to the upper bound. 

    Example:

    class Box<T> {
      private T t; 

      public Box(T t) { this.t = t; }
      public void put( T t) { this.t = t;}
      public T take() { return t; }

      public boolean contains( T t) { return this.t == t; }
      public String toString() { return "Box["+t.toString()+"]"; }
    }
    class Test {
      public static void main(String[] args) {
        Box<? extends Number > box = new Box<Long>(0L);

        box.put(1L);      // error
        box.put(null);    // ok

        box.contains(0L);     // error
        box.toString(); // ok

        Long   l = box.take(); // error
        Number n = box.take(); // ok
      }
    }

    The returned object of "unknown" type is known to be compatible to the upper bound.  Hence we can assign the result of take to a reference variable of type Number in our example.
    LINK TO THIS Technicalities.FAQ603
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard instantiation, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?

    We can call methods through an unbounded wildcard parameterized type that take arguments of the "unknown" type.  But we cannot call methods that return objects of the "unknown" type.
    Compared to the rules for upper bound wildcard parameterized types the rules for wildcard parameterized types with a lower bound wildcard are the other way round. 

    We can call methods through an unbounded wildcard parameterized type that take arguments of the "unknown" type.  But we cannot call methods that return objects of the "unknown" type. 

    Example: 

    class Box<T> {
      private T t; 

      public Box(T t) { this.t = t; }
      public void put( T t) { this.t = t;}
      public T take() { return t; }

      public boolean contains( T t) { return this.t == t; }
      public String toString() { return "Box["+t.toString()+"]"; }
    }
    class Test {
      public static void main(String[] args) {
        Box<? super Long > box = new Box<Number>(0L);
        Number number = new Integer(1);

        box.put(1L);      // ok
        box.put(null);     // ok
        box.put(number);   // error

        box.contains(0L);    // ok
        box.toString();     // ok

        Long   l = box.take(); // error
        Number n = box.take(); // error
        Object o = box.take(); // ok
      }
    }

    Methods that take an argument of the "unknown" type can be invoked with either null or an argument whose type is the lower bound or a subtype thereof.  That is, we can pass a Long to method put through the reference of type Box<? super Long> .  But we cannot pass a Number as an argument, because the compiler does not know whether the Box<? super Long> refers to a Box<Number> or perhaps to a Box<Comparable<Long>> , in which case a Number were inacceptable, because it is not comparable. 

    Methods that return a value of the "unknown" type can be invoked, but only if no assumptions are made regarding the type of the returned object and it is treated like an Object .

    LINK TO THIS Technicalities.FAQ604
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard instantiation, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?

    We cannot call methods that use the type parameter as type argument in an argument type. We can call methods that use the type parameter as type argument in the return type; the returned value is accessible through a wildcard instantiation of the return type. 
    In a wildcard parameterized type, we cannot call methods that use the type parameter as type argument in an argument type  in an argument type.  But, we can call methods that use the type parameter as type argument in the return type; the returned value is accessible through a wildcard instantiation of the return type.  The wildcard instantiation of the return type corresponds to the wildcards instantiation that was used for the method invocation, e.g. a method of Box<? extends Number> would return a ReturnType<? extends Number> and a a method of Box<? super Number> would return a ReturnType<? super Number>

    Unbounded wildcard parameterized type.

    Example (access through unbounded wildcard): 

    class Box< T > {
      private T t; 
      ...
      public boolean equalTo( Box< T > other) { return this.t.equals(other.t); }
      public Box< T > copy() { return new Box<T>(t); }
    }
    class Test {
      public static void main(String[] args) {
        Box<String> stringBox = new Box<String>("abc"); 
        Box<?> unknownBox = stringBox;

        boolean equal = true;
        equal = unknownBox.equalTo( unknownBox ); // error
        equal = unknownBox.equalTo(stringBox); // error

        Box<?> box1 = unknownBox.copy();  // ok
        Box<String> box2 = unknownBox.copy(); // error
      }
    }



    error: equalTo(Box<capture of ?>) in Box<capture of ?> cannot be applied to (Box<capture of ?>)
            equal = unknownBox.equalTo( unknownBox );
                              ^
    error: equalTo(Box<capture of ?>) in Box<capture of ?> cannot be applied to (Box<java.lang.String>)
            equal = unknownBox.equalTo(stringBox);
                              ^
    error: incompatible types
    found   : Box<capture of ?>
    required: Box<java.lang.String>
            Box<String> box2 = unknownBox.copy();
                                              ^
    We cannot call the equalTo method of the Box type through a reference variable of type Box<?> , because the compiler does not know which type of object is expected as an argument of the equalTo method. In our example the reference variable unknownBox refers to a Box<String> and hence only a Box<String> would be acceptable as an argument of the equalTo method.  But from the type information Box<?> the compiler does not know which type of box would be acceptable as an argument.  For this reason the compiler rejects all attempts to invoke the equalTo method. 

    Invocation of the copy method is permitted.  It returns an object of an unknown instantiation of the Box type to which we can refer through a variable of type Box<?> .  More specific information about the instantiation of the Box type is not available and for this reason the assigment to a reference variable of an instantiation different from Box<?> fails. 

    In the example, the parameterized argument and return type happens to be the enclosing type.  This is just by chance. The rules explained above apply in the same way to unrelated parameterized argument and return types.  For instance, if the Box class had methods taking or returning a Comparable<T> the same rules would apply: methods that take arguments of type Comparable<T>  cannot be called and methods that return a Comparable<T> can be called and the result can be assigned to a Comparable<?> .
     

    A note on the error messages and the term "capture of":
    The compiler uses the term "capture of ?" when it refers to the unknown type that the wildcard stands for.  More on the wildcard capture can be found in Technicalities.FAQ501 . The compiler uses the capture of a wildcard in order to denote the signatures of methods in wildcard instantiations. 
    The signature of a method in a wildcard parameterized type is determined by replacing all occurrences of the type parameter by the capture of the parameterized type's wildcard. For instance, the method equalTo (Box<T>) in Box<?> has the signature equalTo(Box<capture of ?>) .   The same method in Box<? extends Number> has the signature equalTo(Box<capture of ? extends Number>) . The method takeContentFrom (Box<? extends T> ) in Box<?> has the signature takeContentFrom(Box<? extends capture of ?>) and the same method in Box<? super Number> has the signature takeContentFrom(Box<? extends capture of ? super Number>)
    What these "capture of capture" things mean is explained below in the discussion of various examples. Just to give you an idea, the term " ? extends capture of ? "  refers to a subtype ("? extends ...") of an unknown type ("capture of ?") , and the term " ? extends capture of ? super Number " refers to subtype  ("? extends ...") of an unknown type ("capture of ? ...")  that is a supertype of Number ("? super Number") . 
     

    Bounded wildcard parameterized types.

    The example above used a reference variable of the unbounded wildcard type Box<?> . If we use a bounded wildcard type such as Box<? extends Number> or Box<? super Number> the same rules apply. 

    Example (access through bounded wilcdard): 

    class Box< T > {
      private T t; 
      ...
      public boolean equalTo( Box< T > other) { return this.t.equals(other.t); }
      public Box< T > copy() { return new Box<T>(t); }
    }
    class Test {
      public static void main(String[] args) {
         Box<Number> numberBox = new Box<Number>(0L);
        Box<? extends Number> unknownBox = numberBox; 

        boolean equal = true;
        equal = unknownBox.equalTo(unknownBox); // error
        equal = unknownBox.equalTo(numberBox); // error

        Box<?> box1 = unknownBox.copy(); // ok
        Box<? extends Number> box2 = unknownBox.copy(); // ok
        Box<Number> box3 = unknownBox.copy();         // error
      }
    }



    error: equalTo(Box<capture of ? extends java.lang.Number>)
    in Box<capture of ? extends java.lang.Number> 
    cannot be applied to (Box<capture of ? extends java.lang.Number>)
            equal = unknownBox.equalTo(unknownBox);
                              ^
    error: equalTo(Box<capture of ? extends java.lang.Number>) 
    in Box<capture of ? extends java.lang.Number> 
    cannot be applied to (Box<java.lang. Number >)
            equal = unknownBox.equalTo(numberBox);
                              ^
    error: incompatible types
    found   : Box<capture of ? extends java.lang.Number>
    required: Box<java.lang.Number>
            Box<Number> box3 = unknownBox.copy();
                                              ^
    The equalTo method cannot be called through a reference variable  of type Box<? extends Number> because the argument type is still an unknown type.  Thanks to the upper bound the compiler knows that the expected argument type must be an instantiation of Box for a type argument that is a subtype of Number , but the compiler still does not know which instantiation exactly. Hence, the compiler cannot make sure that the right type of argument is provided for the method invocation and rejects the method invocation. The effect is exactly the same as for Box<?> , and likewise for Box<? super Number>

    The copy method can be called and the in this case the result can be assigned to a reference variable of the more specific type Box<? extends Number> , instead of just Box<?> .  When invoked on a Box<? super Number> the result would be assignable to a Box<? super Number> .

    LINK TO THIS Technicalities.FAQ605
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard instantiation, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is the capture of a wildcard?

    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?

    We cannot call methods that use the type parameter as an upper wildcard bound  in an argument type, with an exception for access through a lower bound wildcard parameterized type. We can call methods that use the type parameter as the upper wildcard bound in the return type; the returned value is accessible through the unbounded wildcard instantiation of the return type. 
    In an upper bound wildcard parameterized type, we cannot call methods that use the type parameter as an upper wildcard bound  in an argument type. This holds for access through unbounded and upper bound wildcard parameterized types.  Access through a lower bound wildcard parameterized type is possible for certain argument types. 

    We can call methods that use the type parameter as the upper wildcard bound in the return type; the returned value is accessible through the unbounded wildcard instantiation of the return type.  This holds for access through unbounded and lower bound wildcard parameterized types. Access through an upper bound wildcard parameterized type yields a more specific return type, namely a return type that corresponds to the upper bound wildcard instantiation that was used for the method invocation, e.g. a method of Box<? extends Number> would return a ReturnType<? extends Number>

    Unbounded wildcard parameterized type.

    Example (access through unbounded wildcard): 

    class Box< T > {
      private T t; 
      ...
      public void takeContentFrom( Box<? extends T > box) { t = box.t; }
      public Class<? extends T > getContentType() { ... } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Number> numberBox = new Box<Number>(5L); 
        Box<?> unknownBox = numberBox;

        unknownBox.takeContentFrom(numberBox); // error
        unknownBox.takeContentFrom(unknownBox); // error

        Class<Number> type0 = unknownBox.getContentType();       // error
        Class<? extends Number> type1 = unknownBox.getContentType(); // error
        Class<?> type2 = unknownBox.getContentType(); // ok
      }
    }



    error: takeContentFrom(Box<? extends capture of ?>) in Box<capture of ?> 
    cannot be applied to (Box<java.lang.Number>)
            unknownBox.takeContentFrom(numberBox); 
                      ^
    error: takeContentFrom(Box<? extends capture of ?>) in Box<capture of ?> 
    cannot be applied to (Box<capture of ?>)
            unknownBox.takeContentFrom(unknownBox); 
                      ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ?>
    required: java.lang.Class<java.lang.Number>
            Class<Number> type0 = unknownBox.getContentType(); 
                                                           ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ?>
    required: java.lang.Class<? extends java.lang.Number>
            Class<? extends Number> type1 = unknownBox.getContentType(); 
                                                                     ^
    We cannot call the takeContentFrom   through a reference variable of type Box<?> , because the compiler does not know which type of object is expected as an argument of the takeContentFrom method. From the error message you can tell what the compiler find, namely a method with the signature takeContentFrom(Box<? extends capture of ?>) .    The term Box<? extends capture of ?> stands for an instantiation of Box with a type argument of an unknown type that is a subtype of another unknown type. In essence, the argument type is unknown and the compiler has no chance to perform any type checks to make sure the correct type of argument is passed to the method call. And hence the invocation is illegal. 

    Invocation of the getContentType method is permitted.  The return value is of a type that is an unknown instantiation of the Class type to which we can refer through a variable of type Class<?> .  More specific information about the instantiation of the Class type is not available and for this reason the assigment to instantiations such as Class<? extends Number> as Class<Number> fails. 

    Upper bound wildcard parameterized type.

    Let us see what the situation is like when we use a bounded wildcard parameterized type instead of the unbounded one.

    Example (access through upper bound wildcard): 

    class Box< T > {
      private T t; 
      ...
      public void takeContentFrom( Box<? extends T > box) { t = box.t; }
      public Class<? extends T > getContentType() { ... } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Number> numberBox = new Box<Number>(5L); 
        Box<? extends Number> unknownBox = numberBox; 

        unknownBox.takeContentFrom(numberBox); // error
        unknownBox.takeContentFrom(unknownBox); // error

        Class<Number> type0 = unknownBox.getContentType();       // error
        Class<? extends Number> type1 = unknownBox.getContentType(); // ok
        }
    }



    error: takeContentFrom(Box<? extends capture of ? extends java.lang.Number>) 
    in Box<capture of ? extends java.lang.Number> 
    cannot be applied to (Box<java.lang.Number>)
            unknownBox.takeContentFrom(numberBox);
                      ^
    error: takeContentFrom(Box<? extends capture of ? extends java.lang.Number>) 
    in Box<capture of ? extends java.lang.Number> 
    cannot be applied to (Box<capture of ? extends java.lang.Number>)
            unknownBox.takeContentFrom(unknownBox);
                      ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ? extends java.lang.Number>
    required: java.lang.Class<java.lang.Number>
            Class<Number> type1 = unknownBox.getContentType();
                                                           ^
    In an upper bound wildcard parameterized type such as Box<? extends Number> the behavior is the same as in an unbounded wildcard parameterized type. The invocation of takeFromContent is rejected because the argument type in unknown.  The argument type is Box<? extends capture of ? extends Number> which is an instantiation of Box for an unknown subtype of an unknown subtype of Number

    Invocation of the getContentType method is permitted.  The return type is more specific than for the unbounded wildcard case; we can refer to the result through a variable of type Class<? extends Number> .  This is because the return type is Class<capture of ? extends capture of ? extends Number> , which is an unknown subtype of an unknown subtype of Number , that is, a subtype of Number

    Lower bound wildcard parameterized type.

    Last but no least, the invocation through a lower bound wildcard. 

    Example (access through lower bound wildcard): 

    class Box< T > {
      private T t; 
      ...
      public void takeContentFrom( Box<? extends T > box) { t = box.t; }
      public Class<? extends T > getContentType() { ... } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Long>   longBox   = new Box<Long>(0L);
        Box<Number> numberBox = new Box<Number>(0L); 
        Box<Object> objectBox = new Box<Object>(5L);
        Box<? extends Number> unknownNumberBox = numberBox; 
        Box<? super Number>    unknownBox       = numberBox; 

        unknownBox.takeContentFrom(longBox); // ok
        unknownBox.takeContentFrom(numberBox); // ok
        unknownBox.takeContentFrom(objectBox); // error
        unknownBox.takeContentFrom(unknownNumberBox); // ok
        unknownBox.takeContentFrom(unknownBox); // error

        Class<Number> type1 = unknownBox.getContentType();       // error
        Class<? extends Number> type2 = unknownBox.getContentType(); // error
        Class<? super Number> type3 = unknownBox.getContentType();   // error
        Class<?> type4 = unknownBox.getContentType(); // ok
        }
    }



    error: takeContentFrom(Box<? extends capture of ? super java.lang.Number>) 
    in Box<capture of ? super java.lang.Number> 
    cannot be applied to (Box<java.lang.Object>)
            unknownBox.takeContentFrom(objectBox);
                      ^
    error: takeContentFrom(Box<? extends capture of ? super java.lang.Number>) 
    in Box<capture of ? super java.lang.Number> 
    cannot be applied to (Box<capture of ? super java.lang.Number>)
            unknownBox.takeContentFrom(unknownBox);
                      ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ? super java.lang.Number>
    required: java.lang.Class<java.lang.Number>
            Class<Number> type1 = unknownBox.getContentType();
                                                           ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ? super java.lang.Number>
    required: java.lang.Class<? extends java.lang.Number>
            Class<? extends Number> type2 = unknownBox.getContentType();
                                                                     ^
    error: incompatible types
    found   : java.lang.Class<capture of ? extends capture of ? super java.lang.Number>
    required: java.lang.Class<? super java.lang.Number>
            Class<? super Number> type3 = unknownBox.getContentType();
                                                                   ^
    The key difference for lower bound wildcards is that the takeContentFrom   method can be called for certain argument types, namely for those types that are members of the type family denoted by Box<? extends Number> in our example.  It is basically as though the takeContentFrom   method in Box<? super Number> had the signature takeContentFrom(Box<? extends Number>) . Why is this?  The compiler determines the signature of the takeContentFrom   method in Box<? super Number> as takeContentFrom(Box<? extends capture of ? super java.lang.Number>) . Now, what does " ? extends capture of ? super java.lang.Number " mean?  It is an unknown subtype of an unknown supertype of Number .  No matter what this unknown supertype of Number may be, the subtypes of Number would conform to this description. 

    Invocation of the getContentType method is permitted, as expected.  Perhaps surprising is that fact that the return type is not Class<? super Number> , but only Class<?> . This is because the return type is Class<capture of ? extends capture of ? super Number> , which is an unknown subtype of an unknown supertype of Number . Just imagine the unknown supertype of Number were Object , then it could by any type. Hence we know nothing about the return type except that it is an instantiation of class Class and Class<?> correctly describes it.

    LINK TO THIS Technicalities.FAQ606
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized typ?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard instantiation, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is the capture of a wildcard?

    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?

    We can call methods that use the type parameter as a lower wildcard bound in the return type; the returned value is accessible through a wildcard instantiation of the return type (which one depends on the wildcard parameterized type being used). We can call methods that use the type parameter as a lower wildcard bound  in an argument type; the argument type is restricted depending on the wildcard being use.
    In a lower bound wildcard parameterized type, we can call methods that use the type parameter as a lower wildcard bound in the return type. The returned value is accessible through a wildcard instantiation of the return type.  In an unbounded wildcard parameterized type and an upper bound wildcard parameterized type the return type is the unbounded wildcard instantiation of the return type. In a lower bound wildcard parameterized type the return type is more specific, namely the lower bound wildcard instantiation of the return type. That is, a method in class Box that return Comparable<? super T> would return Comparable<?> in Box<?> and Box<? extends Number> and would return Comparable<? super Number> in Box<? super Number>

    This matches the return types of methods with an upper bound wildcard; a method in class Box that return Comparable<? extends T> would return Comparable<?> in Box<?> and Box<? super Number> and would return Comparable<? extends Number> in Box<? extends Number> .  The reasoning for lower bound wildcard parameterized types is the exactly the same as for upper bound wildcard parameterized types.  The more specific return type in a lower bound wildcard parameterized type stems from the fact that the return type of a method that returns Comparable<? super T>   in the instantiation Box<? super Number> would be Comparable<capture of ? super capture of ? super Number> , which boils down to Comparable<? super Number>
     

    More interesting is the invocation of methods that take arguments with lower wildcard bounds. We can call methods that use the type parameter as a lower wildcard bound  in an argument type. In an unbounded wildcard parameterized type and a lower bound wildcard parameterized type the only permitted argument type is the argument type instantiated for type Object . That is, a method in class Box that takes an argument of type Comparable<? super Number> would in the parameterized types Box<?> and Box<? super Number> accept arguments of Comparable<Object> .  Note, this is different from methods that use the type parameter as a upper wildcard bound  in an argument type; they cannot be invokeds at all.  The reason for this permitted argument type is that such a method would have the signature method(Comparable<? super capture of ?>) in an unbounded parameterized type such as Box<?> , and "? super capture of ?" denotes an unknown supertype of an unknown type. The ultimate supertype of all types is Object , hence Comparable<Object> is permitted as an argument type. And likewise in Box<? super Number> , where the signature would involve "? super capture of ? super Number", and again Object is the only type that would fit. 

    In an upper bound wildcard parameterized type with upper bound Bound the permitted arguments types are the types that belong to the family denoted by ArgumentType<? super Bound> .  That is, a method in class Box that takes an argument of type Comparable<? super Number> would in the instantiation Box<? extends Number> accept arguments from the type family Comparable<? super Number> . Note, this is similar to a method with an upper bound argument type in an lower bound parameterized type; e.g. a method in class Box that takes an argument of type Comparable<? extends Number> would in the parameterized type Box<? super Number> accept arguments from the type family Comparable<? extends Number> . The reason for the permitted argument types is that the compiler determines the signature of such a method in Box<? extends Number> as method (Box<? super capture of ? extends Number>) .  " super capture of ? extends Number " means unknown supertype of an unknown subtype of Number , in other words all supertypes of Number

    Unbounded wildcard parameterized type.

    Example (access through unbounded wildcard): 

    class Box< T > {
      private T t; 
      ...
      public int compareTo( Comparable<? super T > other) { return other.compareTo(t); }
      public Box<? super T > copy() { return new Box<T>(t); } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Number> numberBox = new Box<Number>(5L); 
        Box<?> unknownBox = numberBox;

        Comparable<?> comparableToUnknown = new Integer(1);
        Comparable<Object> comparableToObject = ...;
        Comparable<? super Number> comparableToNumber = comparableToObject;

        int compared = 0;
        compared = unknownBox.compareTo(comparableToUnknown); // error
        compared = unknownBox.compareTo(comparableToObject); // ok
        compared = unknownBox.compareTo(comparableToNumber); // error

        Box<?>                box1 = unknownBox.copy(); // ok
        Box<? extends Number> box2 = unknownBox.copy(); // error
        Box<? super Number>   box3 = unknownBox.copy);  // error
        }
    }



    error: compareTo(java.lang.Comparable<? super capture of ?>) in Box<capture of ?> cannot be applied to (java.lang.Comparable<capture of ?>)
            compared = unknownBox.compareTo(comparableToUnknown);
                                 ^
    error: compareTo(java.lang.Comparable<? super capture of ?>) in Box<capture of ?> cannot be applied to (java.lang.Comparable<capture of ? super java.lang.Number>)
            compared = unknownBox.compareTo(comparableToNumber);
                                 ^
    error: incompatible types
    found   : Box<capture of ? super capture of ?>
    required: Box<? extends java.lang.Number>
            Box<? extends Number> box2 = unknownBox.copy();
                                                        ^
    error: incompatible types
    found   : Box<capture of ? super capture of ?>
    required: Box<? super java.lang.Number>
            Box<? super Number> box3 = unknownBox.copy();
                                                      ^
    The example shows that method compareTo can only be invoked for arguments of type Comparable<Object> and that the return type of method copy is Comparable<?>

    Upper bound wildcard parameterized type.

    Example (access through upper bound wildcard): 

    class Box< T > {
      private T t; 
      ...
      public int compareTo( Comparable<? super T > other) { return other.compareTo(t); }
      public Box<? super T > copy() { return new Box<T>(t); } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Number> numberBox = new Box<Number>(5L); 
        Box<? extends Number> unknownBox = numberBox; 

        Comparable<?> comparableToUnknown = new Integer(1);
        Comparable<Object> comparableToObject = ...;
        Comparable<? super Number> comparableToNumber = comparableToObject;

        int compared = 0;
        compared = unknownBox.compareTo(comparableToUnknown); // error
        compared = unknownBox.compareTo(comparableToObject); // ok
        compared = unknownBox.compareTo(comparableToNumber); // ok

        Box<?>                box1 = unknownBox.copy(); // ok
        Box<? extends Number> box2 = unknownBox.copy(); // error
        Box<? super Number>   box3 = unknownBox.copy);  // error
        }
    }



    error: compareTo(java.lang.Comparable<? super capture of ? extends java.lang.Number>) in Box<capture of ? extends java.lang.Number> cannot be applied to (java.lang.Comparable<capture of ?>)
            compared = unknownBox.compareTo(comparableToUnknown);
                                 ^
    error: incompatible types
    found   : Box<capture of ? super capture of ? extends java.lang.Number>
    required: Box<? extends java.lang.Number>
            Box<? extends Number> box2 = unknownBox.copy();
                                                        ^
    error: incompatible types
    found   : Box<capture of ? super capture of ? extends java.lang.Number>
    required: Box<? super java.lang.Number>
            Box<? super Number> box3 = unknownBox.copy();
                                                      ^
    The example shows that method compareTo can only be invoked for arguments from the type family denoted by  Comparable<? super Number> and that the return type of method copy is Comparable<?>

    Lower bound wildcard parameterized type.

    Example (access through lower bound wildcard): 

    class Box< T > {
      private T t;
      ...
      public int compareTo( Comparable<? super T > other) { return other.compareTo(t); }
      public Box<? super T > copy() { return new Box<T>(t); } 
    }
    class Test {
      public static void main(String[] args) {
        Box<Number> numberBox = new Box<Number>(5L); 
        Box<? super Number> unknownBox = numberBox; 

        Comparable<?> comparableToUnknown = new Integer(1);
        Comparable<Object> comparableToObject = ...;
        Comparable<? super Number> comparableToNumber = comparableToObject;

        int compared = 0;
        compared = unknownBox.compareTo(comparableToUnknown); // error
        compared = unknownBox.compareTo(comparableToObject); // ok
        compared = unknownBox.compareTo(comparableToNumber); // error

        Box<?>                box1 = unknownBox.copy(); // ok
        Box<? extends Number> box2 = unknownBox.copy(); // error
        Box<? super Number>   box3 = unknownBox.copy);  // ok
        }
    }



    error: compareTo(java.lang.Comparable<? super capture of ? super java.lang.Number>) in Box<capture of ? super java.lang.Number> cannot be applied to (java.lang.Comparable<capture of ?>)
            compared = unknownBox.compareTo(comparableToUnknown);
                                 ^
    error: compareTo(java.lang.Comparable<? super capture of ? super java.lang.Number>) in Box<capture of ? super java.lang.Number> cannot be applied to (java.lang.Comparable<capture of ? super java.lang.Number>)
            compared = unknownBox.compareTo(comparableToNumber);
                                 ^
    error: incompatible types
    found   : Box<capture of ? super capture of ? super java.lang.Number>
    required: Box<? extends java.lang.Number>
            Box<? extends Number> box3 = unknownBox.copy();
                                                        ^
    The example shows that method compareTo can only be invoked for arguments of type Comparable<Object> and that the return type of method copy is Comparable<? super Number> .
    LINK TO THIS Technicalities.FAQ607
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard parameterized type, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is the capture of a wildcard?

    In a wildcard parameterized type, can I read and write fields whose type is the type parameter?

    It depends on the kind of wildcard.
    In a wildcard parameterized type a field whose type is the type parameter of the enclosing generic class is of unknown type. Depending on the wildcard (whether it is unbounded or has an upper or lower bound) different kinds of access are permitted or disallowed. 

    Unbounded wildcards.

    Assignment to a field of the "unknown" type is rejected because the compiler cannot judge whether the object to be assigned is an acceptable one.  Read access to a field of the "unknown" type is permitted, but the field has no specific type and must be refered to through a reference of type Object

    Example: 

    class Box<T> {
      public T t;  // public just for sake of demonstration
      ...
    }
    class Test {
      public static void main(String[] args) {
        Box<?> box = new Box<String>("abc");

        box.t = "xyz";     // error
        box.t = null;     // ok

        String s = box.t;  // error
        Object o = box.t;  // ok
      }
    }



    Wildcards with an upper bound.

    The same rules apply to wildcard parameterized type with an upper bound wildcard. 

    Example: 

    class Box<T> {
      public T t;  // public just for sake of demonstration
      ...
    }
    class Test {
      public static void main(String[] args) {
        Box<? extends Number > box = new Box<Long>(0L);

        box.t = 1L;      // error
        box.t = null;     // ok

        Number n = box.t; // ok
        Object o = box.t; // ok
      }
    }

    The only difference that a field of "unknown" type is known to be compatible to the upper bound.  Hence we can assign the field to a reference variable of type Number in our example. 


    Wildcards with a lower bound.

    The rules for wildcard parameterized types with a lower bound wildcard are the other way round. We can assign null or a value whose type is the lower bound or a subtype thereof, but we cannot assign a value that is of a supertype of the lower bound. And we must not make any assumptions regarding the type of the field; it must be treated like an Object

    Example: 

    class Box<T> {
      public T t;  // public just for sake of demonstration
      ...
    }
    class Test {
      public static void main(String[] args) {
        Box<? super Long > box = new Box<Number>(0L);
        Number number = new Integer(1);

        box.t = 1L;      // ok
        box.t = null;     // ok
        box.t = number;    // error

        Long   l = box.t;  // error
        Number n = box.t;  // error
        Object o = box.t;  // ok
      }
    }

    LINK TO THIS Technicalities.FAQ608
    REFERENCES Which methods and fields are accessible/inaccessible through a reference variable of a wildcard type?
    Which methods that use the type parameter in the argument or return type are accessible in an unbounded wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in an upper bound wildcard parameterized type?
    Which methods that use the type parameter in the argument or return type are accessible in a lower bound wildcard parameterized type?
    Which methods that use the type parameter as type argument of a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as upper wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    Which methods that use the type parameter as lower wildcard bound in a parameterized argument or return type are accessible in a wildcard parameterized type?
    In a wildcard parameterized type, can I read and write fields whose type is the type parameter?
    What is a wildcard instantiation?
    What is a wildcard?
    What is an unbounded wildcard?
    What is a bounded wildcard?

    Is it really impossible to create an object whose type is a wildcard parameterized type?
     
    It is actually illegal and the compiler tries to prevent it, but there's a workaround.
    The creation of objects of a wildcard parameterized type is discouraged: it is illegal that a wildcard parameterized type appears in a  new expression.

    Example (of illegal creation of objects of a wildcard parameterized type ): 

    class Sequence<E> {
      public Sequence() {...}
      public Sequence(int size) {...}
    public <F extends E> Sequence(F arg) {...}
    public <F extends E> Sequence(F[] a) {...}
      public Sequence(Sequence<? extends E> s) {...}

    }

    Sequence <?> seq1 = new Sequence <?> (); // error
    Sequence <?> seq2 = new Sequence <?> (10);  // error

    Sequence<String> s = new Sequence<String>();
    ... populate the sequence ...

    Sequence<? super String> seq3 =  new Sequence <? super String> ("xyz");  // error
    Sequence< ? super String > seq4 = new Sequence < ? super String > (new String[] {"abc","ABC"});  // error
    Sequence< ? super String > seq5 =  new Sequence < ? super String > (s);                          // error

    The compiler rejects all attempts to create an object of wildcard types such as  Sequence <?> or  Sequence <? super String> .

    The compiler's effort to prevent the creation of objects of a wildcard parameterized type can easily be circumvented.  It is unlikely that you will ever want to create an object of a wildcard parameterized type, but should you ever need one, here's the workaround.

    Instead of directly creating the object of the wildcard parameterized type via a  new expression you define a generic factory method that creates the object.

    Example (of creation of objects of a wildcard parameterized type; workaround ): 

    class Factory {
      public interface Dummy<T> {}
      public final static  Dummy<?> unboundedDummy = null;
      public final static  Dummy<? super String> superStringDummy = null;

      public static <T>  Sequence <T> make( Dummy<T> arg) {
        return new  Sequence <T>();
      }
      public static <T>  Sequence <T> make( Dummy<T> arg, int size) {
        return new  Sequence <T>(size);
      }
      public static <T,S extends T> Sequence<T> make( Dummy<T> d, S arg) {
        return new Sequence<T>(arg);
      }
      public static <T,S extends T> Sequence<T> make( Dummy<T> d, S[] array) {
        return new Sequence<T>(array);
      }
      public static <T> Sequence<T> make( Dummy<T> d, Sequence<? extends T> seq) {
        return new Sequence<T>(seq);
      }
    }

    Sequence <?> seq1 =  Factory.make (Factory. unboundedDummy );          // fine
    Sequence <?> seq2 =  Factory.make (Factory. unboundedDummy ,10 ); // fine

    Sequence<String> s = new Sequence<String>();
    ... populate the sequence ...

    Sequence< ? super String > seq3 =  Factory.make (Factory. superStringDummy , "xyz");  // fine
    Sequence< ? super String > seq4 =  Factory.make (Factory. superStringDummy , new String[] {"abc","ABC"});  // fine
    Sequence< ? super String > seq5 =  Factory.make (Factory. superStringDummy , s);                           // fine 

    The trick is defining a generic factory method that takes a dummy argument for each constructor that you had otherwise used.  This dummy argument must be a of a generic type and is needed so that the compiler can infer the type argument when the factory method is invoked.  When the method is invoked with a dummy argument that is of a wildcard type, then the compiler infers that the factory method's type argument is that particular wildcard and consequently the factory method creates an object of the corresponding wildcard parameterized type.

    In the example the  make method is first invoked twice with a dummy argument of the unbounded wildcard type  Dummy<?> .  The type argument  T is infered as  T:=? (or more precisely  T:=capture of ? ) and hence the  make method creates an object of type  Sequence <?> .  The subsequent three invocations use a dummy argument of the unbounded wildcard type  Dummy<? super String> .  Consequently, the compiler infers  T as  T:=? super String (or more precisely  T:=capture of ? super String ) .  In addition, the compiler infers  S as  S:=String  and checks that  S is a subtype of  T .

    As mentioned above, it is unlikely you will ever need this workaround. 

    LINK TO THIS Technicalities.FAQ609
    REFERENCES What is a wildcard parameterized type?
    Can I create an object whose type is a wildcard parameterized type?
    What is type argument inference?

    Cast and instanceof

    Which types can or must not appear as target type in an instanceof expression?

    Only reifiable types are permitted.
    It is a compile-time error if the reference type mentioned after the instanceof operator does not denote a reifiable type.  In other words, concrete and bounded wildcard parameterized types are NOT permitted in an instanceof expression. 

    Examples: 

            Object o = new LinkedList<Long>();

            System.out.println (o instanceof List);
            System.out.println (o instanceof List<?>);
            System.out.println (o instanceof List<Long>);                 // error
            System.out.println (o instanceof List<? extends Number>);     // error
            System.out.println (o instanceof List<? super Number>);       // error

    The reason for disallowing non-reifiable types (i.e., instantiations of a generic type with at least one type arguments that is a concrete type or a bounded wildcard) in instanceof expression is that these parameterized types do not have an exact runtime type representation.  Their dynamic type after type erasure is just the raw type.   The evaluation of an instanceof expression could at best check whether the object in question is an instance of the raw type.  In the example, the expression (o instanceof List<Long>) would check whether o is an instance of type List , which is a check different from what the source code suggests. In order to avoid confusion, the non-reifiable types are prohibited in instanceof expression. 

    Only the reifiable types (i.e., the raw type and the unbounded wildcard parameterized type) are permitted in an instanceof expression.  The reifiable types do not lose any type information during translation by type erasure. For this reason, the instanceof check makes sense and is allowed.

    LINK TO THIS Technicalities.FAQ701
    REFERENCES What is a reifiable type?
    What is an unbounded wildcard instantiation?

     

    Overloading and Overriding

    What is method overriding?

    When a subtype redefines a method that was inherited from a supertype.
    Overriding is what we do when we derive subtypes from supertypes and specialize the subtype's behaviour by means of implementing in the subtype a specialized version of a method inherited from the supertype.  Overriding is one of the key concepts of object-oriented programming.

    Example (of method overriding): 

    class Super {
      public Type method(Type arg) { ... }

    class Sub extends Super { 
      public Type method(Type arg) { ... }   // overrides Super.method
    }
    The purpose of overriding is polymorphic method dispatch, that is, when the method is invoked through a reference of the supertype and that reference refers to an instance of the subtype then the subtype version of the method is invoked. 

    Example (of polymorphic method dispatch):

    Super ref1 = new Super(); 
    Super ref2 = new Sub(); 

    ref1.method(new Type());  // calls Super.method
    ref2.method(new Type());  // calls Sub.method

    When the overridden method is an abstract method or when the supertype is an interface, the it is said that the overriding method implements the supertype's method declaration. 

    Example (of an overriding method that implements a supertype's method): 

    interface Callable<V> {
      V call();
    }
    class Task implements Callable<Long> {
      public Long call() { ... }   // implements Callable<Long>.call
    }
    LINK TO THIS Technicalities.FAQ801
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?
    Can a method of a non-generic subtype override a method of a generic supertype?
    Can a method of a generic subtype override a method of a generic supertype?
    Can a generic method override a generic one?
    Can a non-generic method override a generic one?
    Can a generic method override a non-generic one?
    Why doesn't method overriding work as I expect it?

    What is method overloading?

    When a class has two methods with the same name, but signatures that are not override-equivalent.
    Method overloading happens among methods defined in the same type, when the methods have the same name and differ in the number or type of arguments. 

    Example (of method overloading): 

    class Container {
      public void remove( int index) { ... }
      public void remove( Object o) { ... } // overloads
    The overloading methods need not necessarily be defined in the same type, but can also be inherited from a supertype. 

    Example (of method overloading): 

    class Super {
      public void method( String arg) { ... }
      public void method( StringBuffer arg) { ... } // overloads

    class Sub extends Super { 
      public void method( StringBuilder arg) { ... } // overloads
    }
    In this example, all three versions of the method overload each other because they have the same name but different argument types. When the method is invoked the compiler picks the best match from the three available candidates.  This process is called overload resolution

    Example (of overload resolution): 

    Sub ref = new Sub();

    ref.method("ABC");                     // calls Super.method(String)
    ref.method(new StringBuilder("ABC"));  // calls Sub.method(StringBuilder)

    The return type is irrelevant for overloading, that is, overloaded methods can have different return types. It is an error if the difference is only in the return type. 

    Example (of method overloading): 

    class Container {
      public boolean remove( Object o) { ... } 
      public Object  remove( int index) { ... } // overloads
      public void    remove( int index) { ... } // error: already defined
    The first two methods overload each other, because they have the same name and different arguments type.  The last two methods are in conflict, because the have the same name and the same argument type and differ only in the return type.  The general rule is that overloaded methods must have the same name but different method signatures , and the return type is not part of a method signature.  A more precise definition of method signature is given in FAQ entry FAQ810 .

    Generic methods can be overloaded as well.

    Example (of overloaded generic methods): 

    class SomeClass {
      public <T>                 void method( T arg) { ... }
      public <T extends Number> void method( T arg)  { ... }    // overloads
      public                    void method( Long arg)  { ... } // overloads
    These three methods have different signatures.  Even the first and the second method differ, because they have different argument types, namely a type parameter with bound Object and a type parameter with bound with bound Number .  This is because the type parameters of a generic method including the type parameter bounds are part of the method signature.

    Method overloading is sometimes confused with method overriding .  Overriding happens among a method in a subtype and a method with the same name inherited from a supertype, if the signatures of those methods are override-equivalent .  This means that methods in the same class never override each other; they can only overload each other.  But methods in a subtype can either override or overload a supertype's method with the same name.  It is sometimes difficult to tell the difference between overloading and overriding.  The rule is: the subtype method overloads the supertype method if it is not override-equivalent. Override-equivalence is explained in more detail in FAQ entry FAQ812 .

    Example (of method overloading vs. overriding): 

    class Super {
      public void method( String arg) { ... } 

    class Sub extends Super { 
      public void method( String arg) { ... }  // overrides
      public void method( StringBuilder arg) { ... } // overloads
    }
    The first method in the subtype has an override-equivalent signature, basically because it has the same signature as the supertype method.    The second method has a different argument type and therefore is not override-equivalent and hence overloads the supertype method.

    The rules for overriding are more complex than sketeched out above; they are discussed in detail in the subsequent FAQ entries.  In particular, overriding does not only require override-equivalent signatures, but additionally a compatible return type and a compatible throws clause.  No such rules apply to overloading. 

    Example (of overloaded methods with different return types and throws clauses): 

    class SomeClass {
      public void    method( String arg) { ... } 
      public void    method( StringBuffer arg) throws IllegalArgumentException { ... } // overloads
      public boolean method( StringBuilder arg) { ... } // overloads
    }
    There is one additional rule, that applies to methods in general: methods declared in the same type (or inherited from a supertype) must not have the same erasure. This is because generics are translated by type erasure.  Two methods with the same erasure would have identical signatures in the byte code and the virtual machine could not distinguish between them.  This is prohibited and the compiler issues an error method if two method have the same erasure.

    Example (of conflicting erasures): 

    class SomeClass {
      public <T extends Number> void method( T arg)  { ... } 
      public                    void method( Number arg) { ... } // error: already defined
    }
    Before type erasure the two methods have different signatures, namely <$T1_extends_Number>method($T1_extends_Number) and method(Number) . After type erasure they both have the signature method(Number) and consequently the compiler reports an error.
    LINK TO THIS Technicalities.FAQ802
    REFERENCES What is overload resolution?

    What is the @Override annotation?

    An annotation that you can attach to a method so that the compiler issues an error if the annotated method does not override any supertype method.
    Overriding and overloading are often confused.  If you are in doubt, you can annotate a subtype's method with the standard annotation java.lang.@Override . The compiler then checks whether the annotated method overrides a supertype method.  If not, it reports an error.

    Example (of using the @Override annotation):

    class Super {
      public <T> void method(T arg) { ... }

    class Sub extends Super { 
      @Override public <T extends Number> void method(T arg) { ... } // error: name clash
    }

    error: method does not override a method from its superclass
            @Override public <T extends Number> void method(T arg) {
             ^
    LINK TO THIS Technicalities.FAQ803
    REFERENCES What is method overriding?
    What is method overloading?

    What is a method signature?

    An identification of a method that consist of the method's name and its arguments types.
    A method signature consists of the method's name and its arguments types.  This is different from a method descriptor , which is the signature plus the return type.  In case of generic methods, the type parameters are part of the signature.  Method signatures play a role in overloading and overriding. 

    Examples: 

     
    Declaration Signature
    void method(String arg) method(String)
    int method(String arg) method(String)
    String method(String arg1, int arg2) throws Exception method(String,int)
    void method(List<? extends Number> list) method(List<?_extends_Number>)
    T method(T arg)
    *) where T is enclosing class's type parameter
    method($T1_extends_Object)
    void add(K key, V val)
    *) with type parameters K and V from enclosing class
    add($T1_extends_Object,$T2_extends_Object)
    <T> T method(T arg) <$T1_extends_Object>method
    ($T1_extends_Object)
    <E> int method(E arg) <$T1_extends_Object>method
    ($T1_extends_Object)
    <T extends Number> T method(T arg) <$T1_extends_Number>method
    ($T1_extends_Number)
    <A extends I&J, B extends J&I> void method(A a, B b) <$T1_extends_I&J,$T2_extends_I&J>method
    ($T1_extends_I&J,$T2_extends_I&J)
    <T> void method(List<T> list) <$T1_extends_Object>method
    (List<$T1_extends_Object>)
    <S extends Number> void method(List<S> list) <$T1_extends_Number>method
    (List<$T1_extends_Number>)
    <E> void sort(List<? extends E> list) <$T1_extends_Object>sort
    (List<? extends $T1_extends_Object>)
    <E extends Comparable<Number>> void sort(List<E> list) <$T1_extends_Comparable<Number>>sort
    (List<$T1_extends_Comparable<Number>>)
    <E extends Comparable<E>> void sort(List<E> list) <$T1_extends_Comparable<$T1_extends_Comparable>>sort
    (List<$T1_extends_Comparable<$T1_extends_Comparable>>)
    <E extends Comparable<? super K>> void sort(List<E> l)
    *) where K is enclosing class's type parameter
    <$T1_extends_Comparable<?_super_$T2_extends_Object>>sort
    (List<$T1_extends_Comparable<$T2_extends_Object>>)
    The terms $T n _extends_Bound 1 &...&Bound n stand for synthetic type variables.  These synthetic names are used in lieu of the original names because the name of a type variable is irrelevant for the signature.  For instance, the methods <T> void method(T arg) and <S> void method(S arg) have the same signature; they are a method named method with one unbounded type parameter and one method parameter whose type is the unbounded type parameter.  Basically, the compiler renames all type variables of a generic method and uses synthetic names instead of the actual names. 

    The terms $Bound 1 &...&Bound n denote the type variable's bounds. For the purpose of a signature, the order of the bounds is irrelevant, that is, " A extends I&J " is equivalent to " B extends J&I ".  Just imagine the compiler would order the bounds alphabetically.

    LINK TO THIS Technicalities.FAQ810
    REFERENCES What is method overriding?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?

    What is a subsignature?

    A method signature that is identical to another method signature, or identical to the erasure of another method signature.
    Subsignatures are relevant in conjunction with overriding.  A prerequisite for overriding is that the subtype method's signature is a subsignature of the supertype method's signature.

    A signature is a subsignature of another signature if:

    • the two signatures are identical, or
    • the signature is identical to the erasure of the other signature.
    Example (subsignatures):
    class Super {
      public void setName( String arg) { ... }
      public void setNames( Collection <String> c) { ... }
      public void printCollection( Collection <?> c) { ... }
    }
    class Sub extends Super {
      public void setName( String arg) { ... }             // subsignature
      public void setNames( Collection c) { ... }          // subsignature
      public void printCollection( Collection c) { ... }   // subsignature
    }
    In the example, the subclass version of the setName method is a subsignature of the superclass version of the method, because it has the same signature.  The subclass versions of the setNames and printCollection methods are subsignatures of the superclass versions of the methods, because their signatures are identical to the erasures of the superclass's methods. 

    Note, that in the case of the setNames method an unchecked warning is issued. The reasons for this warning are discussed in FAQ entry FAQ812 .  The unchecked warning is issued whenever an argument type of the superclass method is a parameterized type and the corresponding argument type in the subclass method is a raw type, unless the parameterized type is the unbounded wildcard instantiation of the generic type.
     

    LINK TO THIS Technicalities.FAQ811
    REFERENCES What is method overriding?
    What is a method signature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?

    What are override-equivalent signatures?

    Two method signatures where one signature is a subsignature of the other.
    Override-equivalent signatures are relevant in conjunction with overriding and overloading. We talk of override-equivalent signatures when a subtype method's signature is a subsignature of a supertype method's signature. 

    The term subsignature was explained in FAQ entry FAQ811 :  A signature is a subsignature of another signature if the signature is identical to the other signature or identical to the erasure of the other signature.

    Override-equivalence is a prerequisite of method overriding.

    • We talk of overriding   if the signature of a subtype's method is override-equivalent to (synonym to: "is a subsignature of") a supertype's method.
    • We talk of overloading if a class has two methods with the same name, but signatures that are not override-equivalent, that is, neither is a subsignature of the other. 
    Example (overloading and overriding):
    class Super {
      public void setName( String arg) { ... }
    }
    class Sub extends Super {
      public void setName( StringBuilder arg) { ... } // overloads
      public void setName( String arg) { ... }  // overrides
    }
    In the example, the two setName methods in the subclass have the same name, but different signatures: one method takes a String argument, the other takes a StringBuilder argument.  As the two signatures are different (and neither is the subsignature of the other), these two methods are not override-equivalent and hence the overload .
    In constrast, the two versions of the setName method taking a String argument in the super- and subclass override .  This is because they have identical and therefore override-equivalent signatures.

    In the example above, the erasure of the methods is irrelevant, because none of the methods has a generic argument type.  Let us consider an examples that involves generic types.

    Example (overloading and overriding):

    class Super {
      public void printCollection( Collection <?> c) { ... }
    }
    class Sub extends Super {
      public void printCollection( List<?> c) { ... } // overloads
      public void printCollection( Collection c) { ... } // overrides
    }
    The two printCollection methods in the subclass have the same name, but different signatures: one method takes a List<?> argument, the other takes a Collection argument.  As the two signatures are different (and neither is the subsignature of the other), these two methods overload .
    In constrast, the two versions of the printCollection method taking a Collection<?> argument in the superclass and a Collection argument in the subclass override although the methods do not have identical signatures.  But the signatures are almost identical: the subclass signature is the erasure of the superclass signature.

    Note, that the converse is not permitted.  If the superclass method had a signature that is identical to the erasure of a subclass method, the compiler would issue an error message.  This is neither overloading nor overriding, but just a name clash.

    Example (neither overloading nor overriding):

    class Super {
      public void printCollection( Collection c) { ... }
    }
    class Sub extends Super {
      public void printCollection( Collection <?> c) { ... } // error
    }

    error: name clash: printCollection(List<?>) in Sub and printCollection(List) in Super 
    have the same erasure, yet neither overrides the other
          class Sub extends Super {
          ^
    The notion of override-equivalent signatures is slightly more complex among generic methods.  See FAQ820 and subsequent entries for further details and examples.
    LINK TO THIS Technicalities.FAQ812
    REFERENCES What is method overriding?
    What is a method signature?
    What is a subsignature?
    When does a method override its supertype's method?
    Can a method of a non-generic subtype override a method of a generic supertype?
    Can a method of a generic subtype override a method of a generic supertype?
    Can a generic method override a generic one?
    Can a non-generic method override a generic one?
    Can a generic method override a non-generic one?

    When does a method override its supertype's method?

    When the subtype's method has a signature that is a subsignature of the supertype's method and the two methods have compatible return types and throws clauses.
    A subtype's method overrides a supertype's method if the subtype's method has a signature that is:
    • identical to the supertype's method's signature, or
    • identical to the erasure of the supertype's method's signature.
    It is said that the subtype method has a subsignature or that the two signatures are override-equivalent .

     
    Subsignatures

    First an example where the subtype's method has the same signature as the supertype's method.

    Example (of overriding methods with identical signatures):

    class Super {
     public void method( String arg) { ... }
    }
    class Sub extends Super {
      public void method( String arg) { ... } // overrides
    }
    Both methods have the same signature, namely method(String) , and for this reason the subclass's method overrides the superclass's method.

    Second, an example where the subtype's method has a signature whose erasure is identical to the signature of the supertype's method.

    Example (of overriding methods with generics involved):

    class Super {
      public void printCollection( Collection <?> c) { ... }
    }
    class Sub extends Super {
      public void printCollection( Collection c) { ... } // overrides
    }
    The erasures of the methods are the same, namely printCollection(Collection) . In this situation, the erased subtype method is considered an overriding version of the non-erased supertype method. 

    This kind of overriding is permitted in order to allow that legacy supertypes can be re-engineered and generified without affecting any existing subtypes of the legacy supertype.  Imagine the supertype had originally not used any generics. In that original situation, the signatures of supertype and subtype method had been identical.  After generification of the supertype the signatures are different.  Without the rule that the subtype method can be the erasure of the supertype method all subtypes would also need to be re-engineered and generified. Fortunately, the additional rule renders this re-engineering effort unnecessary and the generification of the supertype does not affect overriding methods in subtypes.



    There are additional rules for overriding.  When a subtype's method overrides a supertype's method, then:
    • the subtype method's return type must be substitutable for the supertype method's return type, and 
    • the throws clauses of both methods must not be in conflict.
    Substitutable Return Types

    Let us first consider some examples of substitutable and incompatible return types before we look into conflicting throws clauses.

    Example (incompatible return types):

    class Super {
      public void method(String arg) { ... }
    }
    class Sub extends Super {
      public int method(String arg) { ... } // error
    }

    error: method(String) in Sub cannot override method(String) in Super; 
    attempting to use incompatible return type
    found   : int
    required: void
            public int method(String arg) { ... }
                       ^
    Both methods have the same signature, but non-substitutable return types.  A subtype method's return type R Sub is substitutable for a supertype method's return type R Super if:
    • both type are void
    • both types are the same primitive type
    • R Sub is identical to R Super
    • R Sub is a subtype of R Super
    • R Sub is a raw type that is identical to the erasure of R Super
    • R Sub is a raw type that is a subtype of the erasure of R Super
    The last two situations lead to an unchecked warning unless R Super is an unbounded wildcard instantiation.

    Example (substitutable return types):

    class Super {
      public Super         copy() { ... }
      public List<String> getList() { ... }
      public Map           getLinks() { ... }
    }
    class Sub extends Super {
      public Sub                copy() { ... }     // overrides
      public ArrayList<String> getList() { ... } // overrides
      public Map<String,File>   getLinks() { ... } // overrides
    }
    In these examples, the subtype method's return type is a subtype of the supertype method's return type.  The technical term for this kind of substitutability is covariant return types

    Note, that in addition to the regular super-/subtype relationship, an instantiation of a generic type is also considered a subtype of the corresponding raw type.  The getLinks method in the code snippet above illustrates this kind of substitutable return types: the supertype method returns the raw type Map and the subtype method returns the instantiation Map<String,File> .

    The converse is also permitted, namely a supertype version of a method that returns an instantiation and a subtype version that return the corresponding raw type.  But this kind of overriding is not type-safe unless the supertype method's return type is an unbounded wildcard instantiation, as illustrated in the code sample below.

    Example (substitutable return types):

    class Super {
      public Class<?> getType() { ... }
      public Map<String,File> getLinks() { ... }
    }
    class Sub extends Super {
      public Class getType() { ... }  // overrides
      public Map    getLinks() { ... } // overrides with unchecked warning
    }

    warning: getLinks() in Sub overrides getLinks() in Super; 
    return type requires unchecked conversion
    found   : java.util.Map
    required: java.util.Map<java.lang.String,java.io.File>
            public Map getLinks() { ... }
                       ^
    Conflicting throws Clauses

    The supertype and the overriding subtype method must not have conflicting throws clauses.

    Example (conflicting throws clauses):

    class Super {
      public void method() { ... }
    }
    class Sub extends Super {
      public void method() throws UserException { ... } // error
    }
    error: method() in Sub cannot override method() in Super; 

    overridden method does not throw UserException
            public void method() throws UserException { ... }
                        ^
    Both methods have the same signature, but conflicting throws clauses.  The overriding subtype method may not be declared to throw more checked exceptions than the overridden supertype method.  The throws clause of the supertype method must at least contain a supertype of each exception type in the throws clause of the subtype method.

    Example (compatible throws clauses):

    class Super {
      public void method() throws IOException, InterruptedException { ... }
    }
    class Sub extends Super {
      public void method() throws FileNotFoundException { ... } // overrides
    }
    LINK TO THIS Technicalities.FAQ813
    REFERENCES What is method overriding?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    What are covariant-return types?
    What are substitutable return types?
    Can a method of a non-generic subtype override a method of a generic supertype?
    Can a method of a generic subtype override a method of a generic supertype?
    Can a generic method override a generic one?
    Can a non-generic method override a generic one?
    Can a generic method override a non-generic one?
    Why doesn't method overriding work as I expect it?

    What are covariant return types?

    Return types of overriding methods where the supertype method's return type is a supertype of the subtype method's return type.
    When a method defined in a subtype overrides a method defined in a supertype then there are certain rules for the return types of those methods.  Either the return types are identical, or the subtype method's return type is a raw type that is identical to the supertype method's return type.  Java allows one exception from this rule:  the subtype method's return type is allowed to be a subtype of the supertype method's return type, or the subtype method's return type is a raw type that is identical to a subtype of the supertype method's return type. 

    Example (substitutable return types):

    class Super {
      public Super         copy() { ... }
      public List<String> getList() { ... }
      public Map           getLinks() { ... }
    }
    class Sub extends Super {
      public Sub                copy() { ... }     // overrides
      public ArrayList<String> getList() { ... } // overrides
      public Map<String,File>   getLinks() { ... } // overrides
    }
    In these examples, the subtype method's return type is a subtype of the supertype method's return type.  Note, that an instantiation of a generic type is considered a subtype of the corresponding raw type.  The technical term for this kind of return type substitutability is covariant return types .
    LINK TO THIS Technicalities.FAQ814
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?
    What are substitutable return types?

    What are substitutable return types?

    The return type of an overriding subclass method must be substitutable for the superclass method's return type.
    Substitutable return types are required when a method overrides another method.  In that situation the subtype method's return type must be substitutable for the supertype method's return type.

    A subtype method's return type R Sub is considere substitutable for a supertype method's return type R Super if:

    • both type are void
    • both types are the same primitive type
    • R Sub is identical to R Super
    • R Sub is a subtype of R Super
    • R Sub is a raw type that is identical to the erasure of R Super
    • R Sub is a raw type that is a subtype of the erasure of R Super  
    The last two situations lead to an unchecked warning unless R Super is an unbounded wildcard instantiaion.

    Let's take a look at a couple of examples.  In the following code snippet the overriding method has the same return type as its superclass method.

    Example (plain substitutable return types):

    class Super {
      public void          setName(String s) { ... }
      public boolean       equals(Object other) { ... }
      public String        toString() { ... }
    }
    class Sub extends Super {
      public void          setName(String s) { ... }    // overrides
      public boolean       equals(Object other) { ... } // overrides
      public String        toString() { ... }         // overrides
    }
    A little more exciting are the cases in which the subtype method's return type is a subtype of the supertype method's return type.  In this case we talk of covariant return types.

    Example (covariant substitutable return types):

    class Super {
      public Super         copy() { ... }
      public List<String> getNames() { ... }
      public Map           getLinks() { ... }
    }
    class Sub extends Super {
      public Sub                copy() { ... }     // overrides
      public ArrayList<String> getNames() { ... } // overrides
      public Map<String,File>   getLinks() { ... } // overrides
    }
    Worth mentioning is that an instantiation of a generic type is considered a subtype of the corresponding raw type in this context.  The getLinks method illustrates this case.  The supertype method returns the raw type Map and the overriding subtype method returns the more specific type Map<String,File> .

    The converse is permitted, too, but is generally not type-safe. The safe situation is when the subtype's method returns a raw type and the supertype's method returns the wildcard instantiation of the corresponding generic type or of a generic supertype.

    Example (raw substitutable return types):

    class Super {
      public Class<?>           getContentType() { ... }
      public List<?>            asList() { ... }
    }
    class Sub extends Super {
      public Class              getContentType() { ... } // overrides
      public LinkedList         asList() { ... }         // overrides
    }
    The getContentType method in the supertype returns the wildcard instantiation Class<?> and the subtype method's return type Class , the raw type, is considered a substitutable return type.  Note, that the subtype method's return type can additionally be covariant, that is, a raw type that is a subtype of the erasure of the supertype method's return type.  This is illustrated by the asList method.

    When the supertype method's return type is an instantiation different from a wildcard instantation, then the substitution by the raw type in the subclass method is not type-safe and the compiler issues a warning.

    Example (raw substitutable return types):

    class Super {
      public Class<Super> getThisType() { ... }
      public List<String> asStrings() { ... }
    }
    class Sub extends Super {
      public Class       getThisType() { ... } // overrides with unchecked warning
      public LinkedList asStrings() { ... }  // overrides with unchecked warning
    }
    The type-safety problem is that the superclass method getThisType for instance promises that a type token of type Class<Super> is returned, while the subclass method only returns a type token of the raw type Class , which may or may not be compatible with Class<Super> .  The compiler cannot prevent that the subtype method returns an inappropriate type token that is actually of type Class<Alien> .
    LINK TO THIS Technicalities.FAQ815
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?
    What are covariant-return types?
    Can a method of a non-generic subtype override a method of a generic supertype?
    Can a method of a generic subtype override a method of a generic supertype?
    Can a generic method override a generic one?
    Can a non-generic method override a generic one?
    Can a generic method override a non-generic one?
    What is overload resolution?
    How does overload resolution work when generic methods are involved?

    Why doesn't method overriding work as I expect it?

    Can a method of a non-generic subtype override a method of a generic supertype?

    Yes.
    This FAQ entry discusses whether and when methods of a regular, non-generic subtype override methods inherited from a generic supertype.  The question comes up because overriding requires that the method signatures are override-equivalent.  If the supertype is generic then its method signatures might involve a type parameter.  At the same time, the subtype is non-generic and its method signatures will not involve type parameters.  Hence the signatures are different, which raises the question whether overriding is possible when the supertype is generic and the subtype is not.

    The answer is: Yes, it is possible.  A non-generic type can extend or implement a concrete instantiation of a generic supertype and then its methods can override methods from the generic supertype. Here is an example:

    Example (of a non-generic subtype with overriding methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub extends Super <Number> {
      ...
      public void set( Number arg) { ... } // overrides
      public Number get() { ... }    // overrides
    }
    The subtype methods override the corresponding supertype methods.  The subtype derives from a certain instantiation of the supertype, namely Super<Number> in the example.  For this reason, all signatures in the subtype, where T is replaced by Number , are override-equivalent signatures. 

    Let us consider some deviations from this straigth-forward case.  What if we defined the following methods in the subclass?

    Example (of a non-generic subtype with redefined supertype methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      ...
    }
    class Sub extends Super <Number> {
      ...
      public void set( Object arg) { ... } // error: same erasure
      public void set( Long arg) { ... }   // overloads
    }
    The first set method in the subclass is rejected because it has the same erasure as its superclass's version of the set method, namely void set(Object) .
    The second set method in the subclass is not override-equivalent, because its signature is truly different from the supertype method's signature; they have a different argument type.  For this reason it overloads the set method, instead of overriding it.

    Let us consider the get methods. What if we defined the following methods in the subclass?

    Example (of a non-generic subtype with redefined supertype methods):

    class Super <T> {
      ...
      public T get() { ... }
      ...
    }
    class Sub extends Super <Number> {
      ...
      public Object get() { ... } // error: incompatible return type
      public Long get() { ... }   // overrides
    }
    The Sub.get() method that returns Object is recognized as a potentially overriding method, but with incompatible return type, and is therefore rejected with an error method.
    The Sub.get() method that returns Long has an override-equivalent signature, because its return type is a subtype of the supertype method's return type (covariant return type). 
    Naturally, the two get methods cannot coexist in the same class anyway, because their signatures are the same and they only differ in the return type.
    LINK TO THIS Technicalities.FAQ820
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?
    What are covariant-return types?
    What are substitutable return types?
    Can a method of a generic subtype override a method of a generic supertype?
    Why doesn't method overriding work as I expect it?

    Can a method of a generic subtype override a method of a generic supertype?

    Yes, but make sure you do not inadvertently overload instead of override.
    This FAQ entry discusses whether and when methods of a generic subtype can override methods of a generic supertype.  Method signatures in the sub- and the supertype may involve type parameters of the respective enclosing class.  What is the required relationship between type variables in sub- and supertype methods in order to allow for method overriding?

    The answer is: Yes, methods of a generic subtype can override methods of a generic supertype, but it is not always trivial to get it right and it is common that mistakes are made and that  overriding is confused with overloading.

    Let us start with a simple example:

    Example (of a generic subtype with override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub <S> extends Super <S> {
      ...
      public void set( S arg) { ... } // overrides
      public S get() { ... }     // overrides
    }
    The subtype methods override the corresponding supertype methods.  The generic subtype derives from a certain instantiation of the supertype, namely Super<S> in the example, where S is the subtype's type parameter.  Since the names of type parameters are irrelevant for the method signatures, the corresponding methods in super- and subtype have identical signatures, namely set($T1_extends_Object) and get() and identical return types.

    The remainder of this FAQ entry discusses slightly more complex overriding situation for further illustration of the principle.



    Here is another example of successful overriding.

    Example (of a generic subtype with override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub< A , B > extends Super< A > {
      ...
      public void set( A arg) { ... } // overrides
      public A get() { ... }         // overrides
    }
    The signatures and the return types are indentical - a classical example of overriding.  The second type parameter B simply does not appear in the overriding methods' signatures and is therefore irrelevant for overriding.
     

    However, if we slightly change the subtype, our attempt to override the inherited methods goes wrong.  We declare the subtype methods using the type parameter B although we derive from the supertype instantiation on type parameter A

    Example (of a generic subtype without override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub< A , B > extends Super< A > {
      ...
      public void set( B arg) { ... } // error: same erasure
      public B get() { ... }         // error: incompatible return type
    }

    error: name clash: set(B) in Sub<A,B> and set(T) in Super<A> have the same erasure, 
    yet neither overrides the other
        class Sub<A,B> extends Super<A> {
        ^
    error: get() in Sub cannot override get() in Super; 
    attempting to use incompatible return type
    found   : B
    required: A
            public B get() { ... }
                     ^
    The set methods have signatures that are no longer override-equivalent, namely set($T1_extends_Object) in the supertype and set($T2_extends_Object) in the subtype. This is because the compiler distinguishes between different type parameters.  At the same time, both signatures have the identical erasures, namely set(Object) ,  and the compiler rejects the subtype method set with an error message because no two methods in the same type may have identical signatures.

    The get methods have identical signatures, but incompatible return types. Again, because the compiler distinguishes between different type parameters.   For this reason the subtpye method get is rejected with an error message.
     

    Let us modify the subtype a second type and see what happens now.  The modification is that the second type parameter is bounded by the first type parameter.

    Example (of a generic subtype without override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub< A , B extends A > extends Super <A> {
      ...
      public void set( B arg) { ... } // error: same erasure
      public B get() { ... }     // overrides
    }

    error: name clash: set(B) in Sub<A,B> and set(T) in Super<A> have the same erasure, 
    yet neither overrides the other
        class Sub<A,B extends A> extends Super<A> {
        ^


    The set methods still have signatures that are not override-equivalent, namely set($T1_extends_Object) in the supertype and set($T2_extends_$T1) in the subtype. And both signatures still have the same erasure, namely set(Object) . Again, the compiler rejects the subtype method set with an error message.
    The get methods have identical signatures and this time compatible return types, because the type parameter B is a subtype of the type parameter A .  For this reason the subtpye method get overrides the supertype method.



    Let us consider a situation where the subtype's type parameter has different bounds than the supertype's type parameter.

    Example (of a generic subtype with override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub< N extends Number > extends Super< N > {
      ...
      public void set( N arg) { ... } // overrides
      public N get() { ... }     // overrides
    }
    The signatures and the return types of the methods are identical in super and subclass, namely set($T1_extends_Number) with return type void and get() with return type $T1_extends_Number

    Let us change the subtype declaration slightly; we declare subclass methods so that they use the bound in the method signatures instead of the type parameter .

    Example (of a generic subtype with different yet override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub <N extends Number > extends Super< N > {
      ...
      public void set( Number arg) { ... } // overrides
      public Number get() { ... }         // error: incompatible return type
    }
    The set methods now have different signatures, namely set($T1_extends_Number) in the supertype and set(Number) in the subtype.  Normally, this would be overloading, but in this case with type parameters involved the signatures are considered override-equivalent. This is because the supertype's set method takes an argument of type $T1_extends_Number , which is a placeholder for a subtype of Number . The subtype's set method takes an argument of type Number , which means that any argument passed to the set method via a supertype reference is acceptable to the subtype version of the method.

    Consider the example of a concrete parameterization of our super- and subtype in order to understand why it makes sense that the subtype version of the set method is an overriding rather than an overloading version of the supertype method, despite of the different signature.  For illustration we use Sub<Integer> and its supertype Super<Integer> . The two methods involved in overriding are Super<Integer>.set(Integer) and Sub<Integer>.set(Number) . When a supertype reference refers to a subtype object and we invoke the set method through the supertype reference, then we see Super <Integer>.set( Integer ) , but actually invoke the overriding Sub <Integer>.set( Number ) . Is it type-safe?

    Example (of calling the overridden set method):

    Super<Integer> ref = new Sub<Integer>(); 
    ref.set(10);   // calls Sub<Integer>.set(Number)
    All we can pass to Super<Integer>.set(Integer) are objects of type Integer ; they are handed over to Sub<Integer>.set(Number) , which happily accepts the Integer objects because they are subtypes of Number .  And the same is true for all parameterizations of type Sub . because the declared argument type of the supertype method is always a subtype of the declared argument type of the subtype method.  Hence it is type-safe that the subtype version of the set method is considered an overriding version of the supertype's set method.

    The opposite is true for the get methods.  They have identical signatures, but incompatible return types, namely $T1_extends_Number in the supertype and Number in the subtype. If we invoked the subtype's set method via a supertype reference then we would expect a return value of type $T1_extends_Number , which is a placeholder for a subtype of Number , while in fact the subtype method would return a Number reference, which can refer to any arbitrary subtype of Number , not necessarily the one we are prepared to receive.  Hence considering the subtype version of the get method an overriding version of the supertype's get method would not be type-safe and is therefore rejected as an error.
     

    In constrast, the following fairly similar example leads to an overloading situation.

    Example (of a generic subtype without override-equivalent methods):

    class Super <T> {
      ...
      public void set( T arg) { ... }
      public T get() { ... }
    }
    class Sub< N extends Number > extends Super< Number > {
      ...
      public void set( N arg) { ... } // overloads
      public N get() { ... }         // overrides
    }
    The set methods again have different yet similar signatures. This time it is the other way round: we have set(Number) in the supertype and set($T1_extends_Number) in the subtype.  This is overlaoding rather than overriding, because the supertype method has a declared argument type that is a supertype of the subtype method's declared argument type. Overriding would not be type-safe in this situation. 

    To understand it let us use the same concrete parameterization as above, namely Sub<Integer> and its supertype Super<Number> . The two methods in question are Super<Number>.set(Number) and Sub<Integer>.set(Integer) . When a supertype reference refers to a subtype object and we invoke the set method through the supertype reference, then we see Super <Number>.set( Number ) , but would actually invoke Sub <Integer>.set( Integer ) , if this were overrding. This is not type-safe because we could pass an object of type Long to Super<Number>.set(Number) , but the subtype method Sub<Integer>.set(Integer) cannot take it.

    The get methods are not problematic in this example.  They have the identical signatures and covariant return type, namely Number in the supertype and $T1_extends_Number in the subtype. Hence, we have overriding for the get methods.

    Overloading leads to confusing and/or ambiguous method invocations.  Consider for example the instantiation Sub<Number> . In this instantiation we have Super<Number>.set(Number) in the supertype and overloaded version Sub<Number>.set(Number) in the subtype, both methods have the same signature.

    Example (of calling the overloaded set method):

    Integer integer = 10;
    Number  number  = integer;

    Sub<Number> ref = new Sub<Number>(); 
    ref.set(integer); // error: ambiguous
    ref.set(number);  // error: ambiguous


    error: reference to set is ambiguous, 
    both method set(T) in Super<Number> and method set(N) in Sub<Number> match
            ref.set(integer);
               ^
    eror: reference to set is ambiguous, 
    both method set(T) in Super<Number> and method set(N) in Sub<Number> match
            ref.set(number);
               ^
    The point to take notice of is that the set method in Sub<Number> does not override the set method inherited from Super<Number> although in this particular instantiation both methods have the same argument type. 

    This is because the decision whether a subtype method overrides or overloads a supertype method is made by the compiler when it compiles the generic subtype.  At that point in time there is no knowledge regarding the concrete type by which the type parameter N might later be replaced.  Based on the declaration of the generic subtype the two set methods have different signatures, namely set(Number) in the supertype and set($T1_extends_Number) in the generic subtype. In a certain instantiation of the subtype, namely in Sub<Number> , the type parameter N (or $T1_extends_Number ) might be replaced by the concrete type Number .  As a result both set methods of Sub<Number> suddenly have the same arguments type.  But that does not change the fact that the two methods still have different signatures and therefore overload rather than override each other.
     

    LINK TO THIS Technicalities.FAQ821
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    When does a method override its supertype's method?
    What are covariant-return types?
    What are substitutable return types?
    Can a method of a non-generic subtype override a method of a generic supertype?
    Why doesn't method overriding work as I expect it?

    Can a generic method override a generic one?

    Yes.
    This FAQ entry discusses the relationship between generic methods in super- and subtypes with respect to overriding and overloading. 

    Say, we have a supertype with generic methods and we intend to override the generic methods in a subtype.  Which subtype methods are considered overriding versions of the the generic supertype methods?  FAQ entry FAQ823 discusses which non-generic methods in a subtype override a generic method in a supertype.  In this FAQ entry we explore which generic subtype methods override generic methods in a supertype.

    Example (of generic subtype methods overriding generic supertype methods):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      public <S> void set( S arg) { ... } // overrides
      public <S> S get() { ... }    // overrides
    }
    In this example the subtype methods are generic methods and have the same signatures as the supertype methods, namely <$T1_extends_Object>set($T1_extends_Object) and <$T1_extends_Object>get() .  Note, that the names of the type parameters of the generic methods differ in the super- and the subtype.  This, however, does not affect the signatures because the names of type parameters are irrelevant for the signature.

    If the methods have type parameters with different bounds , then they do not override, because the methods have signatures that are not override-equivalent.  Remember, the type parameter bounds are part of a generic method's signature.

    Example (of generic subtype methods overloading generic supertype methods; not recommended):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      public <S extends Number > void set( S arg) { ... } // overloads
      public <S extends Number > S get() { ... }         // overloads
    }
    In this example the subtype methods have the signatures <$T1_extends_Number>set($T1_extends_Number) and <$T1_extends_Number>get() , while the supertype methods have the signatures <$T1_extends_Object>set($T1_extends_Object) and <$T1_extends_Object>get() .  The signatures are clearly different and there is no chance that the subtype methods can ever override the supertype methods. The resulting overload situation makes for "interesting" effects when the methods are invoked; most of the time you will see the compiler complaining about ambiguous method calls.  For this reason complex overloading situations like the one above are generally best avoided.

    Remember that the order of the type parameter bounds does not affect the signature of a generic method.  For this reason, the methods in the following example do override, although they have different type parameter bounds.

    Example (of generic subtype methods overriding generic supertype methods):

    class Super {
      public <T extends Comparable<T> & Serializable > void set(T arg) { ... }
      public <T extends Comparable<T> & Serializable > T get() { ... }
    }
    class Sub extends Super {
      public <S extends Serializable & Comparable<S> > void set(S arg) { ... } // overrides
      public <S extends Serializable & Comparable<S> > S get() { ... }    // overrides
    }
    The respective methods have identical signatures because the order of the type parameter bounds is irrelevant.
    LINK TO THIS Technicalities.FAQ822
    REFERENCES What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What is overload resolution?
    Can a generic method override a non-generic one?
    What is overload resolution?

    Can a non-generic method override a generic one?

    Yes.
    This FAQ entry discusses the relationship between generic and non-generic methods with respect to overloading. 

    Say, we have a supertype with generic methods and we intend to override the generic methods in a subtype.  Which subtype methods are considered overriding versions of the the generic supertype methods?  Before we discuss non-generic subtype methods that override generic supertype methods, let us consider the more obvious case of a subtype with generic methods that override generic methods from the supertype.

    Example (of generic subtype methods overriding generic supertype methods):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      public <S> void set( S arg) { ... } // overrides
      public <S> S get() { ... }    // overrides
    }
    In this example the subtype methods are generic methods and have the same signatures as the supertype methods, namely <$T1_extends_Object>set($T1_extends_Object) and <$T1_extends_Object>get() .  Note, that the names of the type parameters of the generic methods differ in the super- and the subtype.  This, however, does not affect the signatures because the names of type parameters are irrelevant for the signature.

    Now, let us explore an example where non-generic subtype methods override generic supertype methods.  Non-generic subtype methods are considered overriding versions of the generic supertype methods if the signatures' erasures are identical.

    Example (of non-generic subtype methods overriding generic supertype methods):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      public void set( Object arg) { ... } // overrides
      public Object get() { ... }    // overrides with unchecked warning
    }

    warning: get() in Sub overrides <T>get() in Super; 
    return type requires unchecked conversion
    found   : Object
    required: T
            public Object get() {
                          ^
    Here the subtype methods have signatures, namely set(Object) and get() , that are identical to the erasures of the supertype methods.  These type-erased signatures are considered override-equivalent. 

    There is one blemish in the case of the get method: we receive an unchecked warning because the return types are not really compatible.  The return type of the subtype method get is Object , the return type of the supertype method get is an unbounded type parameter.  The subtype method's return type and the supertype method's return type are not compatible , because the subtype method's return type is neither identical to the supertype method's return type nor is it a subtype thereof.  However, the subtype method's return type Object is convertible to the supertype method's return type by means of an unchecked conversion. An unchecked warning indicates that a type check is necessary that neither the compiler nor the virtual machine can perform. In other words, the unchecked operation is not type-safe.  In case of the convertible return types someone would have to make sure that the subtype method's return value is type-compatible to the supertype method's return type, but nobody except the programmer can ensure this.



    The main purpose of allowing that methods with erased signatures override methods with generic signatures is backward compatibility.  Imagine both classes had initially been non-generic legacy classes.  In this initial situation both classes had had methods that take and return Object reference. 

    Example (of legacy classes):

    class Super {
      public void set( Object arg) { ... }
      public Object get() { ... }
    }
    class Sub extends Super {
      public void set( Object arg) { ... } // overrides
      public Object get() { ... }    // overrides
    }
    Later we decide to re-engineer the superclass and turn it into a class with generic methods.

    Example (same as before, but after generification of the supertype):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      publicvoid set( Object arg) { ... } // overrides  ???
      public Object get() { ... }    // overrides  ???
    }
    Now the question is: do the subtype methods still override the generified supertype methods?  The answer is: yes.  This is because subtype methods whose signatures are identical to the erasures of the supertype methods overrides the supertype methods.  That is, we can generify the supertype without affecting the legacy subtypes.



    At last, let us discuss a counter-example where the non-generic subtype methods do not override the generic supertype methods.

    Example (of non-generic subtype method overloading, instead of overriding, generic supertype methods; not recommended):

    class Super {
      public <T> void set( T arg) { ... }
      public <T> T get() { ... }
    }
    class Sub extends Super {
      public void set( String arg) { ... } // overloads
      public String get() { ... }         // overrides with unchecked warning
    }

    warning: get() in Sub overrides <T>get() in Super; 
    return type requires unchecked conversion
    found   : String
    required: T
            public String get() {
                          ^
    Here the subtype method set has the signature set(String) and this signature is not override-equivalent to the supertype method's signature <$T1_extends_Object>set($T1_extends_Object) . This is because the subtype method's signature is different from both the supertype method's signature and the erasure thereof.  As the subtype method set does not override, it overloads.

    The subtype method get on the other hand overrides the supertype method get .  This is because the subtype method's signature is identical to the erasure of the supertype method's signature.  The return types are not compatible, but only convertible by unchecked conversion;  the subtype method's return type String is a subtype of the erasure of the supertype method's return type.  That is, the subtype method's return type is acceptable as a result of the combination of unchecked conversion and covariance.

    The entire subclass is an example of poor design.  The combination of overloading and overriding of corresponding methods is confusing at best.

    LINK TO THIS Technicalities.FAQ823
    REFERENCES What is an unchecked warning?
    What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is overload resolution?
    Can a generic method override a generic one?
    Can a generic method override a non-generic one?

    Can a generic method override a non-generic one?

    No.
    This FAQ entry discusses whether a generic method in a subtype can override an non-generic method inherited from a supertype.  We have seen in FAQ823 that the converse is possible, namely that a regular, non-generic method in a subtype can override a generic method inherited from a supertype. It raises the question whether the same is true if the roles are flipped and a generic method in a subtype attempts to override a non-generic method from a supertype.

    The answer is:  No, generic methods in a subtype can not override non-generic methods in a supertype. Generic subtype methods can only overload non-generic supertype methods.

    Let us consider a superclass with non-generic methods and let us explore why generic methods in subtypes do not override the non-generic supertype methods. 

    Example (of a supertype with non-generic methods and a subtype with generic methods):

    class Super {
      public void set( Object arg) { ... }
      public Object get() { ... }
    }
    class Sub extends Super { 
      public <S> void set( S arg) { ... } // error
      public <S> S get() { ... }    // error 
    }


    error: name clash: <S>set(S) in Sub and set(Object) in Super have the same erasure, 
    yet neither overrides the other
    class Sub extends Super {
    ^
    error: name clash: <S>get() in Sub and get() in Super have the same erasure, 
    yet neither overrides the other
    class Sub extends Super {
    ^
    Although the erasures of the subtype methods have signatures that are identical to the supertype methods' signatures the respective signatures are not override-equivalent.  The override-equivalence only holds when the subtype method's signature is identical to the erasure of the supertype method's signature, but not vice versa.  Consequently, the subtype methods overload, instead of override, the supertype methods.  Moreover, the fact that the erasures of corresponding methods in super- and subtype are identical is in conflict with the rule that a class (the subclass in this case) must not have methods with identical erasures.  As a result the compiler issues error messages.

    Let us consider a slightly different subtype, where again overloading is mixed up with overriding.

    Example (of a supertype with non-generic methods and a subtype with generic methods; not recommended):

    class Super {
      public void set( Object arg) { ... }
      public Object get() { ... }
    }
    class Sub extends Super { 
      public <S extends Number> void set( S arg) { ... } // overloads
      public <S extends Number> S get() { ... } // overloads
    }
    This subclass compiles, but it does not show an example of overriding, but instead of overloading. This is because the supertype methods have the signatures set(Object) and get() , while the subtype methods have the signatures <$T1_extends_Number>set($T1_extends_Number) and <$T1_extends_Number>get() .  In this example, not even the erasures of the signatures are identical, so that there is not the slightest chance that the subtype methods could override the supertype methods.  Instead, the subtype methods overload the supertype methods. What happens when we invoke the overloaded methods?

    Example (of invoking the overloaded methods):

    Sub   sub = new Sub();
    Super sup = sub;

    sup.set("abc");         // calls Super .set(Object)
    sup.set(0);             // calls Super .set(Object)
    Object o = sup.get();   // calls Super .get()

    sub.set("abc");         // calls Super .set(Object)
    sub.set(0);             // calls Sub .<Integer>set(Integer)
    Integer i = sub.get();  // error: ambiguous


    error: reference to get is ambiguous, 
    both method get() in Super and method <S>get() in Sub match
    Integer i = sub.get(); 
                   ^
    The  invocation through a supertype reference leads to calls to the supertype versions of the overloaded method, regardless of the dynamic type of the referenced object.  This is the behavior that is expected of overloaded methods.
    The invocation through a subtype reference leads to a call to the subtype versions of the overloaded set method, provided the argument is of a subtype of Number, and to invocation of the supertype version of the method otherwise. Invocation of the overloaded get method through a subtype reference leads to an error message. Let us see how that happens.

    When the set method is invoked with a String argument, then the compiler finds only one viable method, namely the non-generic set(Object) method  from the supertype. The generic subtype method is not a candidate for this invocation because String is no subtype of Number and hence the possible type argument String is not within bounds. Consequently, the supertype method is called.

    When the set method is invoked with a Integer argument, then the compiler finds two candidates for the invocation of the set method: the non-generic set(Object) method  from the supertype and the parametrization <Integer>set(Integer) inferred from the generic subtype.  Note, the compiler performs type argument inference before is looks for the best match among the candidate methods.  Since the parametrization is the better match, the subtype method is invoked.

    For the invocation of the get method, the compiler finds two candidates: get() from the supertype and <$T1_extends_Number>get() from the subtype.  Neither of the two signatures is more specific and thus the compiler reports an error.  Note, the compiler does not consider the return type when it resolves the overloading and in particular does not perform type inference based on a generic method's return type. In our example it means that the compiler does not infer from the calling context that the instantiation <Integer>get() would be a viable candidate method and then picks it as the better match.  Only the signature, and never the return type, of a method are relevant for overload resolution.

    The overload resolution is slightly different, when explicit instantiations are invoked.

    Example (of invoking the overloaded methods with explicitly specified type arguments):

    Sub   sub = new Sub();
    Super sup = sub;

    Integer n = sub.<Integer>get(); // calls Sub .<Integer>set(Integer)
    sub.<Integer>set(0);            // calls Sub .<Integer>get()

    In this situation the candidate set contains only the respective generic subtype method, because the supertype methods are not generic and for this reason cannot be invoked with explicitly specified type arguments.

    As the examples demonstrate, there is no way that a generic subtype method can override a non-generic supertype method.  Instead, generic subtype methods overload non-generic supertype methods.  Such overloading should generally be avoided because it is confusing and hard to understand.

    LINK TO THIS Technicalities.FAQ824
    REFERENCES What is type argument inference?
    What is method overriding?
    What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is overload resolution?
    Can a generic method override a generic one?
    Can a non-generic method override a generic one?
    Can a generic method override a non-generic one?
    What is overload resolution?

    What is overload resolution?

    The process of determining the best match from a set of overloaded methods.
    When a type has several overloaded methods, then the compiler must decide which method to call when it finds a method invocation expression.  The process of picking the best match from the set of candidate methods is called overload-resolution .

    Example (of method overloading): 

    class Super {
      public void method( String arg) { ... } 
      public void method( StringBuffer arg) { ... } // overloads

    class Sub extends Super { 
      public void method( StringBuilder arg) { ... } // overloads
    }
    In this example, all three versions of the method overload each other because they have the same name but different argument types. When the method is invoked the compiler picks the best match from the three available candidates.  The compiler takes a look at the type of the argument provided to the method call and tries to find a method in the candidate set that accepts this particular type of argument. 

    Example (of overload resolution):

    Sub ref = new Sub();

    ref.method("ABC");                     // calls Super .method(String)
    ref.method(new StringBuilder("ABC"));  // calls Sub .method(StringBuilder)

    In the first method call a String is provided and consequently the compiler invokes the method that takes a String argument.  When a StringBuilder is provided the method with the StringBuilder argument type is the best match.  In both cases there is an exact match.  This is not always so. 

    When there is no exact match the compiler considers various conversions, among them the conversion from a subtype to a supertype (called reference-widening), conversions among primitive types (e.g. int to long ), autoboxing and unboxing (e.g. int to Integer ), and the conversion from a parameterized type to the raw type (called unchecked conversion). By and large, overload resolution is a complex process and can lead to surprising results, in the sense that the compiler picks and invokes a method that nobody had expected would be called.

    This sounds harmless, but can be a serious problem.  For instance, when an overloading method is added to an existing class, then this additional candidate can change the result of overload resolution and thereby inadvertantly change the effect of method invocations in an unrelated part of the program.  This is usually undesired and the resulting bugs are difficult to track down, because symptom and source of the problem are mostly unrelated.

    As a general rule, overloading should be used sparingly and judiciously. 

    LINK TO THIS Technicalities.FAQ830
    REFERENCES What is method overloading?
    What is the @Override annotation?
    What is a method signature?
    What is a subsignature?
    What are override-equivalent signatures?
    Why doesn't method overriding work as I expect it?



    CONTENT PREVIOUS NEXT INDEX
      © Copyright 1995-2022 by Angelika Langer.  All Rights Reserved.    URL: < http://www.AngelikaLanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html  last update: 14 Aug 2018