Ziqi Liu
Ziqi Liu

Reputation: 3171

Generic method return generic type

I have a SimpleMapper which has a constructor taking ResultSet as param:

public abstract class SimpleMapper{
    public SimpleMapper() {}

    public SimpleMapper(ResultSet rs) {}
}

...and I have several subclass from SimpleMapper.

Now I want to write a generic method, converting ResultSet to List<T> where T is subclass of SimpleMapper.

Here is the code:

    public static <T extends SimpleMapper> List<T> resultSetToList(ResultSet rs, Class<? extends SimpleMapper> clazz) throws SQLException {
        List<T> list = new ArrayList<>();
        while (rs.next()) {
            list.add(clazz.getConstructor(new Class[]{ResultSet.class}).newInstance(rs));
        }
        return list;
    }

The compiler is giving this error:

The method add(T) in the type List<T> is not applicable for the arguments (capture#2-of ? extends SimpleMapper)

What am I doing wrong here? I've specified T to be subclass of SimlpeMapper.

Upvotes: 1

Views: 94

Answers (1)

Sweeper
Sweeper

Reputation: 271040

Rather than taking a Class<? extends SimpleMapper>, you should take a Class<T>. This makes sure that the class' constructor produces the same type as the type of list that you are returning:

public static <T extends SimpleMapper> List<T> resultSetToList(ResultSet rs, Class<T> clazz) 
    throws SQLException {
    try {
        List<T> list = new ArrayList<>();
        while (rs.next()) {
            list.add(clazz.getConstructor(ResultSet.class).newInstance(rs));
        }
        return list;
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        // handle the exception in some way...
        // maybe rethrow a RuntimeException?
        throw new RuntimeException("Exception occurred during reflection!", e);
    }
}

Upvotes: 4

Related Questions