Skip to main content

Possible generic bug?

3 replies [Last post]
hackingbear2
Offline
Joined: 2010-02-19

Hi, I believe the following is a bug in generics but I'm too sure about it neither I could find an existing bug about it. I want to see if someone can point one to me, or tell me it is not a bug, before I submit one. Thanks

The codes below won't compile but I think it should because InetAddress should be within the bound of itself.

<br />
import java.net.*;<br />
import java.util.*;<br />
public abstract class TestGeneric {<br />
    abstract E getE();<br />
    abstract  List list();<br />
    abstract List list2();</p>
<p>    static  TestGeneric get(Class clazz) {<br />
        return null;<br />
    }</p>
<p>    public static void main(String ... args) {<br />
        Inet4Address inetAddr4 = get(Inet4Address.class).getE();<br />
        InetAddress inet4Addr = get(Inet4Address.class).getE();<br />
        List inet4AddressList = get(Inet4Address.class).list();<br />
        inetAddr4 = get(Inet4Address.class).list().get(0);<br />
        List inetAddresses = get(Inet4Address.class).list(); // ERROR: InetAddress is not within bound of T<br />
        List inet4Addresses2 = get(Inet4Address.class).list2(); // ERROR: require List<br />
    }<br />
}<br />

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
victorwss
Offline
Joined: 2007-12-05

[code]List inetAddresses = get(Inet4Address.class).list(); // ERROR: InetAddress is not within bound of T
List inet4Addresses2 = get(Inet4Address.class).list2(); // ERROR: require List
[/code]

The returned type of list() and list2() are List, not List.

Though not obvious at a first glance, these types are incompatible and for a good reason. You can add any InetAddress to a List, but this is not true for List. You can't add any InetAddress to a List, so these two list types are incompatible.

Change List to List and it will compile.

This generics subleties are a gotcha in the java language and they are somewhat tricky and counter-intuitive. However, when you get used to it, you see that there are good reasons to be that way. You may find a lot of material about this, specially in SCJP sites and books.

hackingbear2
Offline
Joined: 2010-02-19

> Though not obvious at a first glance, these types are
> incompatible and for a good reason. You can add any
> InetAddress to a List, but this is not
> true for List. You can't add any
> InetAddress to a List, so these two
> list types are incompatible.

but I'm doing the other way around. It is equivalent to (but have different error message)
[code]
List List addrs = addrs4; // ERROR: incompatible type
[/code]

> This generics subleties are a gotcha in the java
> language and they are somewhat tricky and
> counter-intuitive. However, when you get used to it,

Yeah, I spent more times investigating this, e.g. read the "Is List

a supertype of List?" in http://www.angelikalanger.com/GenericsFAQ/ All explanations seem a bit circular. It comes down to that java generics is not covariant or contravariant. Yet, nobody explains why it is not made covariant/contravariant. Is doing so logically incorrect in some/many cases? Any example? (Also C# supports covariant generics; see http://en.wikipedia.org/wiki/C_Sharp_Syntax#Covariance_and_contravariance ) Would supporting covariance making the implementation much harder? It seems to me that if one allows co/contra-variance it would make the rules much simpler for both the implementers and the users; the spec can even get rid of the wild card. These are what I don't get still. Thanks
hackingbear2
Offline
Joined: 2010-02-19

> The codes below won't compile but I think it should
> because InetAddress [b]should be within the bound of
> itself[/b].

sorry, I meant to say the List should be compatible with List because every member of the list is a parent of Inet2Address. Why is this not allowed?