0

Can anyone tell me why the following fails to compile?

class A<K> {

    public <K> A() {
    }

    public static <K> A<K> create(Class<K> k) {
        return new A<K>();
    }
}


public class B<K, V> {

    A<K> ak;

    public <K, V> B(Class<K> klass, V v) {
         ak = A.create(klass);
    }
}

It fails with:

[javac] /home/.../src/B.java:17: error: incompatible types
[javac]         ak = A.create(klass);
[javac]                      ^
[javac]   required: A<K#2>
[javac]   found:    A<K#1>
[javac]   where K#1,V,K#2 are type-variables:
[javac]     K#1 extends Object declared in constructor <K#1,V>B(Class<K#1>,V)
[javac]     V extends Object declared in constructor <K#1,V>B(Class<K#1>,V)
[javac]     K#2 extends Object declared in class B
[javac] 1 error

This is an SSCCE so please don't ask what I am trying to accomplish.

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331
  • Related: http://stackoverflow.com/questions/18688882/what-is-the-purpose-of-type-arguments-in-constructor-call-following-new/18688969#18688969 – Sotirios Delimanolis Feb 04 '14 at 13:25
  • by the way, the `k` parameter in `create` is useless. `create` can be declared as `public static A create()` – newacct Feb 04 '14 at 19:36
  • @newacct the idiom is described here: http://docs.oracle.com/javase/tutorial/extra/generics/literals.html but I grant it may not make sense in this example since it is only an SSCCE. TBH it's not entirely clear to me when using that idiom is not necessary but sometimes adding the class literal explicitly silences xlint compiler warnings. – Marcus Junius Brutus Feb 04 '14 at 20:30
  • @MarcusJuniusBrutus: you pass a class object when you need to use it at runtime. You don't need it here. After you remove it, you may have to explicitly specify the type argument when calling it because the compiler cannot infer it from the arguments. – newacct Feb 04 '14 at 21:26

1 Answers1

5
  • get rid of <K> in the constructor of A
  • get rid of <K, V> in the constructor of B

Constructors do not need to redefine the type parameters of the class. If you do that, they are defined as new type parameters which hide the ones in the class (Eclipse warns you about that).

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • It's interesting though that only the in B's constructor needs to to removed, the in A's constructor can remain. I suppose that's because A's constructor signature does not use K so it's not hiding anything. – Marcus Junius Brutus Feb 04 '14 at 13:56
  • it can remain, in order for the above code to work, but it is still wrong ;) – Bozho Feb 04 '14 at 13:57