public class Util { public static void printBag(Bag<?> bag ) { System.out.println(bag.toString()); } } Bag<String> myBag1 = new Bag("Hello"); Bag<Integer> myBag2 = new Bag(23); Util.printBag(myBag1); // Hello Util.printBag(myBag2); // 23 public static <T> void printBag(Bag<T> bag ) { System.out.println(bag.toString()); } public static <T> Bag<T> getBag(Bag<T> bag ) { return bag; } public static void printBag(Bag<? extends Number> bag ) { System.out.println(bag.toString()); } //Wildcard Lower Bounds //A lower bound wildcard restricts the wildcard to a class or interface and any of its parent types. //There are some general guidelines provided by Java as to when to use what type of wildcard: //An upper bound wildcard should be used when the variable is being used to serve some type of data to our code. //A lower bound wildcard should be used when the variable is receiving data and holding it to be used later. //When a variable that serves data is used and only uses Object methods, an unbounded wildcard is preferred. //When a variable needs to serve data and store data for use later on, a wildcard should not be used (use a type parameter instead). //An upper bound restricts the type parameter to a class or any of its sub-classes and is done this way: SomeClass<? extends SomeType>. A lower bound restricts the type parameter to a class or any of its parent classes and is done this way: SomeClass<? super SomeType>. public class Util { public static void getBag(Bag<? super Integer> bag ) { return bag; } }