I have a question about Java generics. Say I have the following interface:
public static class Something<T> {
public void set(T t) {
}
}
public static interface Manager<T> {
public void add(final String key, final Something<T> o);
public Something<T> get(final String key);
}
An example of usage:
final Manager<Number> m = ...;
m.add("key", new Something<Number>());
m.get("key").set(new Integer(5));
I would also like to be able to add Something<Integer>
, Something<Double>
, ... to the a Manager<Number>
. I would say I have to change the signature of the add-function:
public static interface Manager<T> {
public void add(final String key, final Something<? extends T> o);
public Something<T> get(final String key);
}
final Manager<Number> m = ...;
m.add("key", new Something<Integer>());
m.get("key").set(new Integer(5));
So far, so good. Let's look at a possible implementation of the manager:
public static class ManagerImplementation<T> implements Manager<T> {
protected HashMap<String, Something<T>> map = new HashMap<String, Something<T>>();
public void add(final String key, final Something<? extends T> o) {
map.put(key, o); // <--- here
}
public Something<T> get(final String key) {
return map.get(key);
}
}
This fails, since you cannot add a Something<? extends T>
to a Map<X, Something<T>>
. So let's change this:
public static class ManagerImplementation<T> implements Manager<T> {
protected HashMap<String, Something<? extends T>> map = new HashMap<String, Something<? extends T>>();
public void add(final String key, final Something<? extends T> o) {
map.put(key, o);
}
public Something<T> get(final String key) {
return map.get(key); // <--- here
}
}
This fails since map.get(key)
returns Something<? extends T>
while the get-function is required to return Something<T>
, as defined in the interface.
What is the common approach to solve this?
Thanks!
Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.
In a nutshell, generics enable types (classes and interfaces) to be parameters when defining classes, interfaces and methods. Much like the more familiar formal parameters used in method declarations, type parameters provide a way for you to re-use the same code with different inputs.
A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.
To be an effective Java developer now, you must understand the details of generics and how they are used in Java 8. Designed for the intermediate level Java user, this video explores how generic classes and methods are defined, how they enforce bounded types through wildcards, and how you can use them in your own code.
Inside your class you are always using Something<? extends T>
, thus in your public get
method you must convert the inside world to the outside world format. E.g. you can simply cast the result of map.get(key)
to Something<T>
:
return (Something<T>) map.get(key); // <--- here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With