Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - generics & wildcards & interface versus implementation

Tags:

java

generics

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!

like image 889
user1284566 Avatar asked Oct 08 '13 09:10

user1284566


People also ask

What are generics in Java?

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.

Why do we use generics in Java?

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.

What is a generic Java class?

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.

Does Java 8 have generics?

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.


1 Answers

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
like image 182
LastFreeNickname Avatar answered Oct 28 '22 12:10

LastFreeNickname