Home > Software design >  java generics wildcards casting issue
java generics wildcards casting issue

Time:07-02

I have method as below

   void meth(List<?> list) {
       List<Integer> integers = (List<Integer>)list; //how do I make sure am casting correctly to List < Integer >? what if list passed as List< String > , then this will throw some RunTime Exceptions, how to avoid this?
    }

In above snippet, for meth(), am not sure which type of Arraylist will be passed, it could be List or List etc, based on type of list type, I have to assign it to another list correctly, how can I achieve this?

CodePudding user response:

Basically ... you can't. Since you could call meth (as you have written it) with a List<String> parameter, there can always be runtime exceptions.

Solutions:

  • Declare meth as public void meth(List<Integer> list) so that you can't call it like this meth(someStringList). That avoids the unchecked type cast and eliminates the possibility of a class cast exception.

  • Use list like this in meth.

    void meth(List<?> list) {
        for (Object o: list) {
            Integer i = (Integer) o;
            // ...
        }
    }
    

    We can still get the class cast exception, but at least we get rid of the compiler error about unchecked type casts.

  • Use a @SuppressWarning annotation to suppress the compiler warning about the unchecked type cast. Once again, you could get the exceptions.


Unfortunately, given Java's generic type parameter erasure, there is no way that the body of meth (as written) can find out what kind of list it has been called with at runtime. And it won't work with a named type parameter either.

CodePudding user response:

I verified that it does not throw exception. With type erasure, all generics are convert to Object. Generics are for compiler to enforce type during compile time.

   static List<Integer> meth(List<?> list){
      return (List<Integer>) list;
   }
   
    public static void main(String[] args) {
        List<String> strings = new ArrayList<>();
        strings.add("world");
        strings.add("hello");
        List<Integer> integers = meth(strings);
        System.out.println(integers);
    }

Console:

[world, hello]

You can try the code here: https://onlinegdb.com/z7DmGAJUI

  • Related