1

Let's assume, there is a method that returns an Object, but we know it is some sort of typed List (e.g. LinkedList<Long> or ArrayList<String>):

public abstract Object open(); 

Directly using its return value

List<Long> result = (List<Long>)dialog.open(); 

will cause a warning such as:

Type safety: Unchecked cast from Object to List


To overcome this problem, we can cast to List<?> and then check each list item individually:

List<?> result = (List<?>)dialog.open(); List<Long> safeResult = new LinkedList<Long>(); for (Object obj: result) { if (obj instanceof Long) { safeResult.add((Long)obj); } } 

Now I thought, wouldn't it be nice to have a generic method that can cast an Object (that is known to contain a List) to any typed instance of List.

This is the closest I could get:

private <T> List<T> doSafeCast(Object listObject, Class<T> type) { List<T> result = new LinkedList<T>(); if (listObject instanceof List) { List<?> list = (List<?>)listObject; for (Object obj: list) { if (type.isInstance(obj)) { result.add(type.cast(obj)); } } } return result; } 

Now I can use it like this:

List<Long> safeResult = this.doSafeCast(dialog.open(), Long.class); 

However, now I am bound to have LinkedLists as result only.


Is it possible to specify the list type by passing an additional parameter, too?

I would want to to something like this:

List<Long> safeResult = this.doSafeCast(dialog.open(), Long.class, ArrayList.class); List<String> anotherSafeResult = this.doSafeCast(anotherDialog.open(), String.class, LinkedList.class); 

I know that all this seems overly complicated and I could just add @SuppressWarnings("unchecked") to my initial unsafe cast, if I were sure that the dialog will always return the desired type. But I came up with this idea of having a general method to do such safe casts and now I want to know, if this is possible at all. So please don't suggest other solutions, I just want to learn about using generics a little more, here. :-) Thank you.

1 Answer 1

1

Yes, you can. By simply introducing another type-parameter for the method and up-bound it to List:

private <T, L extends List<T>> List<T> doSafeCast(Object listObject, Class<T> type, Class<L> listClass) { List<T> result = listClass.newInstance(); if (listObject instanceof List) { List<?> list = (List<?>) listObject; for (Object obj : list) { if (type.isInstance(obj)) { result.add(type.cast(obj)); } } } return result; } 

Note that you have to handle few possible exceptions.

Sign up to request clarification or add additional context in comments.

4 Comments

Uuuh, I was so close. :-) I tried the same, but with L implements List.
Well, this gets me Type safety: The expression of type List needs unchecked conversion to conform to List<Long> now, when I call doSafeCast(). :-D
This is the best you can do, actually, because at Runtime you can't specify the generic-parameter for the class you want to instantiate.
All right, so that makes the overall idea pretty useless, if I end up having a type safety warning again.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.