在不破坏构建的情况下将泛型引入Java代码

时间:2008-11-13 16:24:27

标签: java generics

以下代码无法编译:

public class GenericsTest {    
    public static void main(String[] args) {
        MyList<?> list = new MyList<Object>();
        Class<?> clazz = list.get(0);

        // Does not compile with reason 
        // "Type mismatch: cannot convert from Object to Class"
        MyList list2 = new MyList();
        Class clazz2 = list2.get(0);
    }
    static class MyList<T> extends ArrayList<Class<T>> {
    }
}

我想这样做是为了在不破坏构建的情况下将泛型引入旧代码。

这是编译器(eclipse和javac)中的错误还是我在这里遗漏了什么?将泛型引入MyList还有什么其他可能性?

修改

澄清:

我有通用类

public class MyList extends ArrayList<MyObject> {}

public class MyObject {}

和使用MyList的代码

MyList list = new MyList();
...
MyObject o = list.get(0);

现在在开发过程中,我看到我想向MyObject引入泛型

public class MyObject<T> {}

现在我想在MyList中使用这个新的通用的东西

public class MyList<T> extends ArrayList<MyObject<T>> {}

但这确实打破了我的构建。有趣的是

public class MyList<T> extends ArrayList<MyObject<T>> {
    public MyObject<T> get(int i) {
        return super.get(i);
    }
}

将允许旧代码

MyList list = new MyList();
...
MyObject o = list.get(0);

编译。

好的,似乎当我介绍这个泛型时,我将不得不将所有对MyList的调用更改为通用形式。我希望旧代码只引入警告而不是错误。

5 个答案:

答案 0 :(得分:12)

我认为你并不了解泛型如何运作。

MyList<?> list = new MyList<Object>();
Class<String> clazz= list.get(0);

此代码段无法编译,因为您告诉编译器list将保留Class<Object>类型 - 然后在下一行中您希望它返回{{1} }。 Java中的通用系统无法像你想象的那样转换基于继承的泛型使用的类型。

如果您希望Class<String>持有list,那么您需要将其声明为 - 或者,如果您希望它能够容纳任何类型,那么您不能在没有演员。

Class<String>

MyList<String> list = new MyList<String>();
Class<String> clazz = list.get(0);

第二个代码段不起作用,因为当您使用原始类型时,仍然需要将MyList<?> list = new MyList<Object>(); //generates a warning about an unchecked cast Class<String> clazz = (Class<String>) list.get(0); 返回的Object强制转换为您正在使用的声明类型(这一直是这种情况)

get()

答案 1 :(得分:1)

我在这台机器上没有编译器,但这应该可行。

public class GenericsTest {    
    public static void main(String[] args) {
        MyList<Object> list = new MyList<Object>();
        Class<?> clazz= list.get(0);

    }


    static class MyList<T> extends ArrayList<Class<? extends T>> {
    }
}

答案 2 :(得分:1)

在您的示例中,MyList是您要更新的旧代码以支持泛型?如果是这样,我的列表应该包含哪种类型的对象?

正如其他地方提到的那样,编译错误是有效的。这是因为正在访问原始列表而不将其转换为类。因此,代码试图将Object分配给Class的引用。它相当于:

Object o = new Object();
Class c = o;

哪根本无法编译。此外,为了充分利用泛型,你应该支持Class&lt;?&gt;而不是Class。

答案 3 :(得分:0)

在您的示例中,第二个示例不起作用,因为您没有使用泛型,因此这意味着get()方法将返回一个Object,您需要将其强制转换为Class。如果没有为MyList指定类型:

  

MyList list2 = new MyList();

然后你失去了Generics的优点,你需要在调用get()方法时强制转换对象,就像在好日子里一样。

答案 4 :(得分:-1)

你试过了吗?

Class clazz2 = list2.get(0).getClass();

阅读: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#getClass()