如何在Java中转换通用List类型?

18

我有一个名为Customer的类(没有基类)。

我需要将LinkedList转换为List。 有没有什么简单的方法可以做到这一点?

只是让你知道,我需要将它转换为List。没有其他类型可行。(我正在使用Slim和FitNesse开发测试夹具)。


编辑:好吧,我想我需要在这里提供代码示例。

import java.util.*;
public class CustomerCollection
{
    protected LinkedList<Customer> theList;

    public CustomerCollection()
    {
        theList = new LinkedList<Customer>();
    }

    public void addCustomer(Customer c){ theList.add(c); }
    public List<Object> getList()
    {
        return (List<? extends Object>) theList;
    }
}

所以根据Yuval A的评论,我最终按照他的建议编写了代码。但是我遇到了这个错误:

CustomerCollection.java:31: incompatible types
found   : java.util.List<capture#824 of ? extends java.lang.Object>
required: java.util.List<java.lang.Object>
        return (List<? extends Object>)theList;
               ^
1 error

那么,正确的转换方式是什么?


你应该从一开始就给出代码示例,我会在一秒钟内更新我的答案... - Yuval Adam
10个回答

32

你不需要进行强制类型转换。因为LinkedList实现了List接口,所以这里不需要进行类型转换。

即使你想将其向下转型为一组ObjectList,你也可以使用泛型,代码如下:

LinkedList<E> ll = someList;
List<? extends Object> l = ll; // perfectly fine, no casting needed

现在,在您编辑之后,我理解您试图做什么,这是不可能的,除非像这样创建一个新的List

LinkedList<E> ll = someList;
List<Object> l = new LinkedList<Object>();
for (E e : ll) {
    l.add((Object) e); // need to cast each object specifically
}

否则我将解释为什么这是不可能的。考虑以下内容:

LinkedList<String> ll = new LinkedList<String>();
List<Object> l = ll; // ERROR, but suppose this was possible
l.add((Object) new Integer(5)); // now what? How is an int a String???

更多信息请参见Sun Java泛型教程。希望这能澄清问题。


你误解了我的意思。请考虑:[代码] LinkedList<E> ll = someList; List<Object> l =ll [/代码]。这样可以吗?我的意思是这个。 - jrharshath
按照您说的做了,但问题仍然存在。编辑了问题并添加了代码示例和遇到的错误。 - jrharshath
1
你的getList()方法是否可以返回List<?>? - Andrew Duffy
@Andrew 不行。这就是主要问题。 - jrharshath

20

这是我做类型转换的可怕解决方案。我知道,我知道,我不应该把这样的东西发布出去,但它对于将任何对象转换为任何类型非常有用:

public class UnsafeCastUtil {

    private UnsafeCastUtil(){ /* not instatiable */}

    /**
    * Warning! Using this method is a sin against the gods of programming!
    */
    @SuppressWarnings("unchecked")
    public static <T> T cast(Object o){
        return (T)o;
    }

}

使用方法:

Cat c = new Cat();
Dog d = UnsafeCastUtil.cast(c);

现在,我要向编程之神祈求宽恕我的罪过...


1
我对此完全没问题。我经常这样做。我通常在库中“内部”执行此操作(从不将其暴露在任意转换中)。然后,我构造我的代码以使错误的转换不可能发生。因此,当我知道可以安全地将List<E>强制转换为List<B>时,因为我的代码结构要求E是B的子类(而且我不需要反向转换),那么我就可以放心使用了。有时,“黑客”是正确和干净的事情。 - luis.espinal

3

我为了这个目的编写了这个函数,虽然有些丑陋但它能正常工作。

public static <T> Collection<T> cast(Collection<? super T> collection, Class<T> clazz){
    return (Collection<T>)collection;
}

2
clazz是用来做什么的?没有被使用。 - nachokk
2
clazz is purely used to determine what T is, so collection can be casted to a collection of T - Populus

1
>    public List<Object> getList()

为什么要返回List ?您可能想返回List(不带泛型),因为它等效,但这会使以下代码起作用:
LinkedList<Customer> theList = new LinkedList<Customer>();

public List getList() {
    return theList;
}

在不同泛型类型的列表之间进行转换很棘手,而且在这里似乎是不必要的。

当然,您应该返回类型为List<Customer> ...


1
你应该从你的方法中返回一个List<?>。直观地,getList()返回一个列表,以便调用者可以检索其中的项。List<?>(相当于List<? extends Object>)允许这种功能。然而,你将无法通过返回的列表将任何东西放入其中,因为那不是类型安全的;但我认为这也不是你需要的。
public List<?> getList()
{
    return theList;
}

0

只需放置

public static List<Object> getList() {
    List l = test;
    return l;
}

0

基于julman99答案

@SuppressWarnings("unchecked")
public <T> List<T> cast(List<? super T> list){
    return (List<T>) list;
}

0

LinkedList 实现了 List 接口,因此你可以实现

List< String > list1 = new LinkedList< String >(); 

或者你想从LinkedList< String >转换为List< int >?在这种情况下,你必须挑选每个单独的元素并将其转换为整数。


我想要将LinkedList<String>转换为List<Object>。我曾经认为这应该是自动的,因为LinkedList IS_A List,而String IS_A Object。但是今天我发现它并不是这样的。:( - jrharshath

0
如果您的列表是通用类型,例如:
``` ArrayList strList = new ArrayList(); strList.add("String1"); Object o = strList; ```
那么以下方法应该可以工作。
public <T> List<T> getListObjectInBodyOfType(Class<T> classz, Object body) {
    if(body instanceof List<?>){
        List<?> tempList = (List<?>)body;
        if(tempList.size() > 0 && tempList.get(0).getClass().equals(classz)){
            return (List<T>) body;
        }
    }
    return new ArrayList<T>();
}

如何使用它?

List<String> strList1 = getListObjectInBodyOfType(String.class, o);

正如我之前提到的,如果对象包含泛型列表,则可以工作,但如果您传递一个包含混合类型元素的非泛型列表,则无法工作。


-1

List是一个接口,LinkedList是该接口的具体实现。大多数情况下,隐式转换会起作用,将LinkedList分配给List,或将其传递给期望List的函数,它应该只是“工作”的。

如果必要,也可以进行显式转换。

//This is valid
List<Customer> myList = new LinkedList<Customer>();

//Also Valid
List<Customer> myList = (List<Customer>) new LinkedList<Customer>();

3
显式转换永远不是必须的。 - Yuval Adam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接