How to cast generic List types in java?
Asked Answered
A

10

18

Well, I have a class Customer (no base class).

I need to cast from LinkedList to List. Is there any clean way to do this?

Just so you know, I need to cast it to List. No other type will do. (I'm developing a test fixture using Slim and FitNesse).


EDIT: Okay, I think I need to give code examples here.

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;
    }
}

So in accordance with Yuval A's remarks, I've finally written the code this way. But I get this error:

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

So, what's the correct way to do this cast?

Angleaangler answered 25/5, 2009 at 9:0 Comment(1)
you should have given code examples from the start, I'll update my answer in a second...Kathrynekathy
K
32

You do not need to cast. LinkedList implements List so you have no casting to do here.

Even when you want to down-cast to a List of Objects you can do it with generics like in the following code:

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

Now, after your edit I understand what you are trying to do, and it is something that is not possible, without creating a new List like so:

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

and I'll explain why this is not possible otherwise. Consider this:

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???

For more info, see the Sun Java generics tutorial. Hope this clarifies.

Kathrynekathy answered 25/5, 2009 at 9:3 Comment(4)
You missed my point. Consider: [code] LinkedList<E> ll = someList; List<Object> l =ll [/code]. Is this okay? I mean this.Angleaangler
Did what you said, but problem persists. Edited the question to add code example and the error encountered.Angleaangler
Is it possible for your getList() method to return List<?>?Lustick
@Andrew No. Thats the main problem.Angleaangler
H
21

Here's my horrible solution for doing casting. I know, I know, I shouldn't be releasing something like this into the wild, but it has come in handy for casting any object to any type:

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;
    }

}

Usage:

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

Now I'm going to pray to the gods of programming for my sins...

Hop answered 30/5, 2011 at 5:14 Comment(1)
I am absolutely ok with this. I do it regularly. I usually do this "internally" in libraries (never exposed in the wild for arbitrary casts). Then I structure my code to make a wrong cast impossible. So when I know that I can safely cast List<E> to List<B> because the structure of my code obligates E to be a subclass of B (and I don't need to reverse the cast), then I'm good to go. Sometimes a "hack" is the right and clean thing to do.Decade
C
3

I did this function for that, ugly but it works

public static <T> Collection<T> cast(Collection<? super T> collection, Class<T> clazz){
    return (Collection<T>)collection;
}
Calc answered 28/3, 2013 at 20:51 Comment(2)
and clazz is for what ? is not usedMolybdic
clazz is purely used to determine what T is, so collection can be casted to a collection of TVoluntarism
K
1
>    public List<Object> getList()

Why are you returning List<Object>? You might as well return List (without generics) since that is equivalent but would make the following code work:

LinkedList<Customer> theList = new LinkedList<Customer>();

public List getList() {
    return theList;
}

Casting between Lists with different generic types is tricky and seems unnecessary here.

Of course you should be returning type List<Customer> ...

Kaliope answered 25/5, 2009 at 11:37 Comment(0)
F
1

You should return a List<?> from your method. Intuitively, getList() returns a list so that the caller can retrieve the items inside. List<?> (which is equivalent to List<? extends Object>) allows that functionality. However, you won't be able to put anything into it via the returned list, because that would not be type safe; but I don't think that is what you need anyway.

public List<?> getList()
{
    return theList;
}
Foster answered 25/5, 2009 at 17:42 Comment(0)
R
0

LinkedList implements List, so you can implement

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

Or do you want to cast from LinkedList< String > to List< int >? in this case you have to pick every single element and convert it to an integer.

Roesch answered 25/5, 2009 at 9:7 Comment(1)
I want to convert from LinkedList<String> to List<Object>. That (i used to think) should be automatic, coz LinkedList IS_A List, and String IS_A Object. But I found out today that it is not. :(Angleaangler
K
0

just put

public static List<Object> getList() {
    List l = test;
    return l;
}
Kacey answered 30/7, 2011 at 10:30 Comment(0)
M
0

If your list is of a generic type for eg

ArrayList<String> strList = new ArrayList<String>(); strList.add("String1"); Object o = strList;

then Following method should work

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>();
}

How to use it?

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

as I mentioned before it works if the Object contains generic list, this won't work if you pass a non-generic list with mixed type of elements

Mineral answered 14/7, 2014 at 14:44 Comment(0)
C
0

Based on julman99 answer:

@SuppressWarnings("unchecked")
public <T> List<T> cast(List<? super T> list){
    return (List<T>) list;
}
Clinician answered 5/1, 2023 at 17:43 Comment(0)
S
-1

List is an interface, LinkedList is a concrete implementation of that interface. Much of the time an implicit cast will work, assign a LinkedList to a List, or pass it to a function expecting a List and it should just `work'.

An explicit cast can also be done if necessary.

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

//Also Valid
List<Customer> myList = (List<Customer>) new LinkedList<Customer>();
Strobile answered 25/5, 2009 at 9:8 Comment(1)
an explicit cast is never necessary.Kathrynekathy

© 2022 - 2024 — McMap. All rights reserved.