// generics/Wildcards.java // (c)2016 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. // Exploring the meaning of wildcards public class Wildcards { // Raw argument: static void rawArgs(Holder holder, Object arg) { //- holder.set(arg); // warning: [unchecked] unchecked call to set(T) // as a member of the raw type Holder // holder.set(arg); // ^ // where T is a type-variable: // T extends Object declared in class Holder // 1 warning // Can't do this; don't have any 'T': // T t = holder.get(); // OK, but type information is lost: Object obj = holder.get(); } // Similar to rawArgs(), but errors instead of warnings: static void unboundedArg(Holder holder, Object arg) { //- holder.set(arg); // error: method set in class Holder // cannot be applied to given types; // holder.set(arg); // ^ // required: CAP#1 // found: Object // reason: argument mismatch; // Object cannot be converted to CAP#1 // where T is a type-variable: // T extends Object declared in class Holder // where CAP#1 is a fresh type-variable: // CAP#1 extends Object from capture of ? // 1 error // Can't do this; don't have any 'T': // T t = holder.get(); // OK, but type information is lost: Object obj = holder.get(); } static T exact1(Holder holder) { return holder.get(); } static T exact2(Holder holder, T arg) { holder.set(arg); return holder.get(); } static T wildSubtype(Holder holder, T arg) { //- holder.set(arg); // error: method set in class Holder // cannot be applied to given types; // holder.set(arg); // ^ // required: CAP#1 // found: T#1 // reason: argument mismatch; // T#1 cannot be converted to CAP#1 // where T#1,T#2 are type-variables: // T#1 extends Object declared in method // wildSubtype(Holder,T#1) // T#2 extends Object declared in class Holder // where CAP#1 is a fresh type-variable: // CAP#1 extends T#1 from capture of ? extends T#1 // 1 error return holder.get(); } static void wildSupertype(Holder holder, T arg) { holder.set(arg); //- T t = holder.get(); // error: incompatible types: // CAP#1 cannot be converted to T // T t = holder.get(); // ^ // where T is a type-variable: // T extends Object declared in method // wildSupertype(Holder,T) // where CAP#1 is a fresh type-variable: // CAP#1 extends Object super: // T from capture of ? super T // 1 error // OK, but type information is lost: Object obj = holder.get(); } public static void main(String[] args) { Holder raw = new Holder<>(); // Or: raw = new Holder(); Holder qualified = new Holder<>(); Holder unbounded = new Holder<>(); Holder bounded = new Holder<>(); Long lng = 1L; rawArgs(raw, lng); rawArgs(qualified, lng); rawArgs(unbounded, lng); rawArgs(bounded, lng); unboundedArg(raw, lng); unboundedArg(qualified, lng); unboundedArg(unbounded, lng); unboundedArg(bounded, lng); //- Object r1 = exact1(raw); // warning: [unchecked] unchecked method invocation: // method exact1 in class Wildcards is applied // to given types // Object r1 = exact1(raw); // ^ // required: Holder // found: Holder // where T is a type-variable: // T extends Object declared in // method exact1(Holder) // warning: [unchecked] unchecked conversion // Object r1 = exact1(raw); // ^ // required: Holder // found: Holder // where T is a type-variable: // T extends Object declared in // method exact1(Holder) // 2 warnings Long r2 = exact1(qualified); Object r3 = exact1(unbounded); // Must return Object Long r4 = exact1(bounded); //- Long r5 = exact2(raw, lng); // warning: [unchecked] unchecked method invocation: // method exact2 in class Wildcards is // applied to given types // Long r5 = exact2(raw, lng); // ^ // required: Holder,T // found: Holder,Long // where T is a type-variable: // T extends Object declared in // method exact2(Holder,T) // warning: [unchecked] unchecked conversion // Long r5 = exact2(raw, lng); // ^ // required: Holder // found: Holder // where T is a type-variable: // T extends Object declared in // method exact2(Holder,T) // 2 warnings Long r6 = exact2(qualified, lng); //- Long r7 = exact2(unbounded, lng); // error: method exact2 in class Wildcards // cannot be applied to given types; // Long r7 = exact2(unbounded, lng); // ^ // required: Holder,T // found: Holder,Long // reason: inference variable T has // incompatible bounds // equality constraints: CAP#1 // lower bounds: Long // where T is a type-variable: // T extends Object declared in // method exact2(Holder,T) // where CAP#1 is a fresh type-variable: // CAP#1 extends Object from capture of ? // 1 error //- Long r8 = exact2(bounded, lng); // error: method exact2 in class Wildcards // cannot be applied to given types; // Long r8 = exact2(bounded, lng); // ^ // required: Holder,T // found: Holder,Long // reason: inference variable T // has incompatible bounds // equality constraints: CAP#1 // lower bounds: Long // where T is a type-variable: // T extends Object declared in // method exact2(Holder,T) // where CAP#1 is a fresh type-variable: // CAP#1 extends Long from // capture of ? extends Long // 1 error //- Long r9 = wildSubtype(raw, lng); // warning: [unchecked] unchecked method invocation: // method wildSubtype in class Wildcards // is applied to given types // Long r9 = wildSubtype(raw, lng); // ^ // required: Holder,T // found: Holder,Long // where T is a type-variable: // T extends Object declared in // method wildSubtype(Holder,T) // warning: [unchecked] unchecked conversion // Long r9 = wildSubtype(raw, lng); // ^ // required: Holder // found: Holder // where T is a type-variable: // T extends Object declared in // method wildSubtype(Holder,T) // 2 warnings Long r10 = wildSubtype(qualified, lng); // OK, but can only return Object: Object r11 = wildSubtype(unbounded, lng); Long r12 = wildSubtype(bounded, lng); //- wildSupertype(raw, lng); // warning: [unchecked] unchecked method invocation: // method wildSupertype in class Wildcards // is applied to given types // wildSupertype(raw, lng); // ^ // required: Holder,T // found: Holder,Long // where T is a type-variable: // T extends Object declared in // method wildSupertype(Holder,T) // warning: [unchecked] unchecked conversion // wildSupertype(raw, lng); // ^ // required: Holder // found: Holder // where T is a type-variable: // T extends Object declared in // method wildSupertype(Holder,T) // 2 warnings wildSupertype(qualified, lng); //- wildSupertype(unbounded, lng); // error: method wildSupertype in class Wildcards // cannot be applied to given types; // wildSupertype(unbounded, lng); // ^ // required: Holder,T // found: Holder,Long // reason: cannot infer type-variable(s) T // (argument mismatch; Holder // cannot be converted to Holder) // where T is a type-variable: // T extends Object declared in // method wildSupertype(Holder,T) // where CAP#1 is a fresh type-variable: // CAP#1 extends Object from capture of ? // 1 error //- wildSupertype(bounded, lng); // error: method wildSupertype in class Wildcards // cannot be applied to given types; // wildSupertype(bounded, lng); // ^ // required: Holder,T // found: Holder,Long // reason: cannot infer type-variable(s) T // (argument mismatch; Holder // cannot be converted to Holder) // where T is a type-variable: // T extends Object declared in // method wildSupertype(Holder,T) // where CAP#1 is a fresh type-variable: // CAP#1 extends Long from capture of // ? extends Long // 1 error } }