Generics Flashcards
How can we restrict what class or interface could be used as a type argument in generics?
We can accomplish this by assigning an upper bound. An upper bound will limit the type parameter to a parent type or any of its child types. Let’s see how this is done:
public class Box <T extends Number> { private T data; }
How can we use upper bounds with generic methods?
public static <T extends Number> boolean isZero(T data) { return data.equals(0); }
How do we create a type parameter with multiple bounds with generics?
public class Box <T extends Number & Comparable<T>> { private T data; }
Here we specify multiple bounds (Number and Comparable) for type parameter T using the & operator between the different upper bounds. It’s important to note that when defining multiple bounds, any upper bound that is a class, in our example Number, must come first, followed by any interfaces, in our example Comparable<T>.</T>
What is wildcards used for in generics?
We can make our code even more general when we don’t need the more strict type checking of using type parameters by using wildcards. A wildcard, denoted by the ? symbol, represents an unknown type when used with generic methods.
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
What is a lower-bound wildcard?
We can also provide a lower bound when working with wildcards. A lower bound wildcard restricts the wildcard to a class or interface and any of its parent types. For example:
public class Util { public static void getBag(Bag<? super Integer> bag ) { return bag; } }
What are some important things to note about lower bounds?
- They cannot be used with generic type parameters, only wildcards.
- A wildcard cannot have both a lower bound and upper bound, in this case, it’s best to use a type parameter.
When and how should we use wildcards?
- 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).
How do we define generics?
The diamond operator (<>) is used to define generic classes, interfaces, or methods.
What is the advantages of using generics?
- Generics provide compile-time type safety and bug detection as opposed to raw types.
- Generics remove the need to explicitly type cast when working with generics types.
- Generics allow you to create algorithms that don’t depend on a specific data type through methods, interfaces, and classes.
Can we use generics with primitive types?
No. Only wrapper classes are provided to allow primitive values to be used with generic code.