1

I have some generic code:

T1<T1<T1<?>>> v1 = null;
T1<T1<?>> v2 = v1;

for which I get this error:

incompatible types: T1<T1<T1<?>>> cannot be converted to T1<T1<?>>

Why can't I assign here?

In case of non-nested wildcard all works fine:

    T1<T1<?>> v1 = null;
    T1<?> v2 = v1;

Do not have such problem.

Definition of T1

class T1<T> { }
GhostCat
  • 137,827
  • 25
  • 176
  • 248
talex
  • 17,973
  • 3
  • 29
  • 66
  • 2
    What is the real problem you intend to solve by creating a 3 level nesting like that? – GhostCat Aug 14 '18 at 09:19
  • It is simplified example. In real app I have different classes on each level, some of them have more than one generic parameter. – talex Aug 14 '18 at 09:21
  • I am pretty sure there is a nice duplicated question for your request, but alas, I can't find it right now ;-) – GhostCat Aug 14 '18 at 09:26
  • 1
    Something like this comes pretty close to what you're asking: https://stackoverflow.com/q/26766704 But technically this is also a dupe of: https://stackoverflow.com/q/2745265 Long story short: you'd need `T1 extends T1>> v2 = v1;` – Jorn Vernee Aug 14 '18 at 09:30

1 Answers1

2

You cannot assign this because T1<T1<T1<?>>> is not an instance of T1<T1<?>>.

Why? Let's analyze this:

  • T1<T1<T1<?>>>: an instance of T1 whose type parameter is exactly T1<T1<?>>
  • T1<T1<?>>: an instance of T1 whose type parameter is exactly T1<?>

So you cannot assign because type parameter T1<?> is not exactly the same as type parameter T1<T1<?>>.

As John Vernee pointed out in his comment, you'd need T1<? extends T1<?>> for this to work because:

  • T1<? extends T1<?>>: an instance of T1 whose type parameter is T1<?> or its subtype (like T1<T1<?>>)

EDIT: Why can you assign T1<T1<?>> (or even T1<T1<T1<?>>) to T1<?>? Because:

  • T1<?>: an instance of T1 whose type parameter can by anything

To take it even further: T1<T1<T1<T1<?>>> could be assigned to the following types having fewer T1s:

  • T1<? extends T1<? extends T1<?>>
  • T1<? extends T1<?>
  • T1<?>
  • Object (which corresponds to pure ?)

I hope it's clear now how this nested generic subclassing works.

PS. Follow a link in this comment, where wildcard nesting is explained in more detail.

Tomasz Linkowski
  • 4,386
  • 23
  • 38