Java generics with unbounded wildcard?

后端 未结 3 1593
孤城傲影
孤城傲影 2021-01-03 13:24

I have an interface to convert object to string:

public interface Converter {
    String asString(T object);
}

And a map to store

3条回答
  •  臣服心动
    2021-01-03 13:54

    First, you should encapsulate the map inside a helper class like this, whose operations preserve the invariant (that Class maps to Converter):

    public class ConverterMap {
        Map, Converter> converterMap = new HashMap, Converter>();
        public  void addConverter(Class clazz, Converter converter) {
            converterMap.put(clazz, converter);
        }
        @SuppressWarnings("unchecked")
        public  Converter getConverter(Class clazz) {
            return (Converter)converterMap.get(clazz);
        }
    }
    

    Now, to break down the task, let's take the small step of writing a function that takes any object and converts it based on the converter map (assuming the object's class is in the converter map):

    ConverterMap cm = new ConverterMap;
    private static String convert(Object x);
    

    This seems simple, but is harder than it looks, because you will run into a special case of the Java type system in how it types .getClass(). You will have the problem of convincing the compiler that x is an instance of the parameter of x.getClass(). The best way to solve this is:

    @SuppressWarnings("unchecked")
    private static  String convert2(Class clazz, Object x) {
        return cm.getConverter(clazz).asString((T)x);
        // you can alternately do clazz.cast(x) instead of the unchecked cast (T)x
    }
    private static String convert(Object x) {
        return convert2(x.getClass(), x);
    }
    

    And then you can solve the rest of the problem:

    for (Object datum : data) {
        stringData.add(convert(datum));
    }
    

提交回复
热议问题