Exercise 4 - Box
The Basics
Box::equals(Object obj)
Box::equals(Object obj)Two boxes are the same if the content of the box equals each other, as decided by their respective
equalsmethod.
The problem arose here is how to cast obj from Object to a Box, which is a generic type. The implementatino is as follows,
@Override
public boolean equals(Object obj) {
if (obj instanceof Box<?>) {
Box<?> box = (Box<?>) obj;
return this.content.equals(box.content);
}
return false;
}In Line 3, we check whether obj's runtime type is a subtype of any Box, (here we should use Box<?> to avoid using rawtype). If so, we can than use Box<?> to cast obj to a Box and then access its content.
Factory method
The factory method enables us to make our constructor private. For example, the factory method of for our Box<T> should be
public static <T> Box<T> of(T obj) {
if (obj == null) {
return null;
}
return new Box<T>(obj);
}An Empty Box
static field of same generic type in a generic type
static field of same generic type in a generic typeAs we have seen that in generics, we cannot use class-level type parameters in static field or static method. So, here, to define a static field with type Box, we can
use unbounded wildcard for generalizability
specify a specific type, like
Box<String>(but this is not generalizable and thus not recommended)
Box<?> means it is a Box of any type. But to create an instance of Box, Java needs to know what is the type you want to put inside the box.
Here, new Box<>(null) works because Java perform type inference to infer the type argument. T in Box<T> will be inferred to as Object based on the type inference process in class.
private static final Box<?> emptyBox = new Box<?>(null); doesn't work because wildcard (e.g. <?> here) cannot be used as a type arguement (a.k.a wildcard is not a type!)
PECS
For the filter function, the parameter is BooleanCondition, we call the test function to test the content of the Box, thus here the parameter is a consumer, meaning that we should use lower-bounded wildcards so that any BooleanCondition that is a supertype of the type of the content in the box, which is T, should be able to be tested!
Implement Your Own Conditions
extends or implement a generic type - 1
extends or implement a generic type - 1This tells us that we must instantiate our generic type when we try to extends or implements a generic type. See more from Instantiate a Generic Type.
Transforming a Box
Declare a type parameter in a non-static method
Similarly, the transformer here is a consumer! And to return a Box<U>, we need to define a type parameter in the non-static method map so that we can return a Box<U>.
Box in a Box
extends or implement a generic type - 2
extends or implement a generic type - 2This actually practices the third way to parameterize a generic type.
In this way, we pass the type parameter T from BoxIt to Transformer<T, Box<T>>, so in Transformer<T, B<T>> the T can be considered as the type argument!
Last updated