Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: use generics in method return that differs from generic class parameter

Tags:

java

generics


    class SomeClass<E> {
       Map<String, String> someMethod();
    }

And usage


    SomeClass a = new SomeClass();
    a.someMethod().get("foo") // returns object, not string!

    //This code would not even compile
    String s = a.someMethod().get("foo");

But if I remove generalization (<E>) from SomeClass -- it works.

It also works if I extract this method to interface and use interface in declaration:


    interface Foo {
     Map<String, String> someMethod();
    }

    class SomeClass implements Foo {
    //.....
    }

    Foo foo = new SomeClass();

    String s = foo.someMethod().getString("A");//it works

Why it happens? Where can I read about it? What is the best work-around? Thanks.

like image 626
Ilya Kazakevich Avatar asked Dec 29 '22 12:12

Ilya Kazakevich


1 Answers

The solution isn't to make SomeClass non-generic - it's to avoid using the raw type. For example, this works fine:

import java.util.*;

class SomeClass<E> {
   Map<String, String> someMethod() {
      return null;
   }
}

public class Test {
    public static void main(String[] args) {
        SomeClass<Integer> a = new SomeClass<Integer>();
        String value = a.someMethod().get("foo");
    }
}

Admittedly it's slightly odd that the method effectively has type erasure applied if you use the raw type - but you should basically avoid doing that to start with.

I can't currently find any explanation for the behaviour of the raw type in the JLS, but section 4.8 does include this warning:

The use of raw types is allowed only as a concession to compatibility of legacy code. The use of raw types in code written after the introduction of genericity into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will disallow the use of raw types.

like image 174
Jon Skeet Avatar answered Dec 31 '22 00:12

Jon Skeet