0

假设我有以下代码:

Object li = new Object(); 

// this causes a compiler warning   

ArrayList<String> lo = (ArrayList<String>)(li); 

好的,我已经编辑了问题,对不起,我犯了一个错误,重点是,因为当我们投射到目标时会导致编译时警告,其目标是参数化类型,有没有更好的解决方案以便我可以防止代码引起编译时警告?

在处理数组时,我们有 Arrays.newInstance 来代替强制转换的使用。


原始问题的代码:

// List<String> is a superclass of ArrayList

List<String>      listOne =  new List<String>();

ArrayList<String> listTwo = (List<String>) listOne; 
4

2 回答 2

1

如果您处于这种情况,您有两种选择。首先是进行未经检查的演员表:

Object o = getObjectFromSomewhereMysterious();
List<String> lst = (List<String>)o; //compiler warning

这将导致您提到的警告-这意味着,由于类型擦除,在运行时强制转换只能检查以确保o是 a List,而不是 a List<String>。因此,例如 if ois a强制转换HashMap将立即失败,但如果它是 aList<Integer>它不会失败......直到稍后您尝试处理lst类似 a的元素String。这被称为“污染堆”

//some later place in the code path - who knows, it could be miles away
String str = lst.get(0); //ClassCastException if lst isn't really a List<String>

只要您可以确定强制转换是安全的,您就可以抑制编译器警告:

@SuppressWarnings("unchecked") //this is safe because blah blah blah
List<String> lst = (List<String>)o;

始终记录为什么可以抑制警告 - 这有助于保持代码的可维护性。

第二种选择是安全的:

List<?> lst = (List<?>)o;

这意味着lstList某种未知类型。它允许您避免未经检查的演员表,但限制了您可以做什么lst

lst.add("some string"); //compiler error

该声明是非法的,因为我们不知道是否lst允许持有Strings。我们能做的最好的就是从中读取,但即便如此,元素也只能输入为Object

Object element = lst.get(0);
于 2012-08-31T06:18:48.060 回答
1

您不能实例化 List,因为List 是一个 interface

ArrayList是一个实现List接口

你可以这样做:

List<String> listOne  =  new ArrayList<String>();
List<String> listTwo  =  listOne;

当使用listOne的代码不关心它是哪种 List 时,这是正确的方法。

这是一个示例,说明了为什么这是一个好方法:

List<String> someList = createList();

这里someList设置为名为 createList 的方法的返回。在这种情况下,我们不知道someList是什么类型的列表。可以是ArrayList、Vector、Stack等……只要createList返回一个实现List接口的对象,上面的代码就可以工作。使用这种方法,可以在不影响调用它的代码的情况下修改createList中的代码。

你也可以这样做:

ArrayList<String> listOne  =  new ArrayList<String>();
ArrayList<String> listTwo  =  listOne;

这不是那么灵活,但它允许您将列表专门视为 ArrayLists。

从技术上讲,您可以这样做,但这不是一个好主意:

List<String>      listOne  =  new ArrayList<String>();
ArrayList<String> listTwo  =  (ArrayList<String>) listOne;

最好通过声明一个 List 并实例化一个 ArrayList来对接口进行编程。

这是一个示例,显示了对接口进行编程的一些好处:

public static void testIt() {

    List someList;
    ArrayList anArrayList;

    /*
     *  all of these will work 
     */

    someList = createVectorAsList();
    printList(someList);

    someList = createStackAsList();
    printList(someList);

    someList = createArrayListAsList();
    printList(someList);

    // you CAN assign an ArrayList to a List

    someList = createArrayList();
    printList(someList);

    // you CAN treat an ArrayList as a List

    anArrayList = createArrayList();
    printList(anArrayList);


    /* 
     *  none of these work 
     */

    // you can NOT assign List to an ArrayList

    anArrayList = createStackAsList();
    anArrayList = createVectorAsList();

    // you can NOT pass anything but an ArrayList to printArrayList

    printArrayList(createStackAsList());
    printArrayList(createVectorAsList());
    printArrayList(createArrayListAsList());

}

/** Prints any List */

public void printList(List someList) {
    for (Object o : someList) {
        System.out.println(o.toString());
    }
}

/** Prints ArrayLists only */

public void printArrayList(ArrayList someList) {
    for (Object o : someList) {
        System.out.println(o.toString());
    }
}

public List createVectorAsList() {
    Vector v = new Vector();
    v.add("I am a vector element");
    return v;
}

public List createStackAsList() {
    Stack s = new Stack();
    s.add("I am a stack element");
    return s;
}

public List createArrayListAsList() {
    ArrayList ar = new ArrayList();
    ar.add("I am an array list element");
    return ar;
}

public ArrayList createArrayList() {
    ArrayList ar = new ArrayList();
    ar.add("My array is not returned as a list...");
    return ar;
}
于 2012-08-31T03:01:23.893 回答