开发者

Quick legacy to generics conversion question

How to declare mixedList with generics for such snapshot without modifying the rest of the code?

List mixedList = new ArrayList();
if(flagA) {
 开发者_如何学Go   ClassA a = new ClassA(); //comes from elsewhere
    mixedList.add(a)
} else {
    List<ClassB> bList = new ArrayList<ClassB>();  //comes from elsewhere
    mixedList = bList; //error
}

I can do:

List<Object> mixedList = new ArrayList<Object>();
if(flagA) {
    ...
} else {
    ...
    mixedList.addAll(bList);
}

but is there a way to avoid changing the code?


It's not safe to assign bList (List<ClassB>) to mixedList (List<Object>).

The service from which you obtained bList might retain a reference to it; this service will assume its list contains only ClassB instances. If you were allowed to assign that list to a List<Object> reference, you could then add any type of object to the list without a warning. But when the service, thinking that every element in its list was a ClassB, attempted to access the elements, a ClassCastException would be raised.

Creating a new List<Object>, and adding elements to it with add() or addAll(), prevents this "type pollution". You can safely modify this copy of the list, and let the source of the list keep its own copy "pure."


I don't believe it can be done.

Rant:

Java Generics imo are simply not worth the headache beyond simple collection use. I can live with casts. And as we all know, generics give the veneer of type safety but under the covers there is type monkey patching.

/Rant done:

This works but you will need to do reference swizzling for one of the respective block - here I'm opting for a List<?> for mixedList and swizzling for the case flagA:

public static void foo(boolean flagA) {
    List<?> mixedList = new ArrayList<Object>();
    if(flagA) {
        ClassA a = new ClassA(); //comes from elsewhere
        List<Object> mixedList2 = (List<Object>) mixedList; // mod
        mixedList2.add(a);
    } else {
        List<ClassB> bList = new ArrayList<ClassB>();  //comes from elsewhere
        mixedList = bList;
    }
}


It's hard to know what you are asking, especially the part about "not changing the code" (why ask a question then). Nevertheless, it seems you can give some bounding to Class for your list:

List<? extends Class<?>> mixedList = new ArrayList<Class<?>>();
List<Class<String>> bList = new ArrayList<Class<String>>(); 
bList.add(String.class);
mixedList = bList;

This code compiles (String used for easy compile check)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜