Java: generically return a typed Set specified by parameter

Christoph Strehl :

I want to have a method that generically creates a list of a specified interface. I can't seem to get it so that I don't have to cast or that I loose my type-safety.

This version requires casting of the Set and produces unsafe type cast warnings:

public static Set<? extends Setting> getSettings(Class<? extends Setting> className){
    Set<? extends Setting> result = new HashSet<>();
    try {
        Setting settingsObject = className.getDeclaredConstructor().newInstance();
        // do something with it and populate result-set
    } catch (Exception e) {
        e.printStackTrace();
    }

    return result;
}   


public static void main(String[] args)  {
    Set<LiabilitySetting> liabilitySettings = (Set<LiabilitySetting>) getSettings(LiabilitySetting.class);
    for (LiabilitySetting s: liabilitySettings) {
        s.doSomething();
    }

}

while with this version I need to cast the elements of the set before using them

public static Set<Setting> getSettings(Class<? extends Setting> className){
    Set<Setting> result = new HashSet<>();
    try {
        Setting settingsObject = className.getDeclaredConstructor().newInstance();
        // do something with it and populate result-set
    } catch (Exception e) {
        e.printStackTrace();
    }

    return result;
}   


public static void main(String[] args)  {
    Set<Setting> liabilitySettings = getSettings(LiabilitySetting.class);
    for (Setting s: liabilitySettings) {
        ((LiabilitySetting) s).doSomething();;
    }

}

I feel there is a way of writing my method without loosing type-safe and without having to cast. Any ideas?

Kayaman :

Use a bounded type parameter instead.

public static <T extends Setting> Set<T> getSettings(Class<T> className) {

The wildcard ? tells the compiler that it's some subclass of Setting (or Setting itself), but the compiler doesn't know whether the ? in the Class is the same as the ? in the Set.

When you bind it to a type parameter, the compiler still knows that T is a subclass of Setting or Setting, but now it knows that the Set and the Class have the same type, removing the need for a cast.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=295388&siteId=1