Generische Java-Methoden in generischen Klassen

Wenn Sie eine generische Klasse in Java erstellen (die Klasse verfügt über generische Typparameter), können Sie generische Methoden verwenden (die Methode verwendet generische Typparameter)?

Betrachten Sie das folgende Beispiel:

public class MyClass {
  public <K> K doSomething(K k){
    return k;
  }
}

public class MyGenericClass<T> {
  public <K> K doSomething(K k){
    return k;
  }

  public <K> List<K> makeSingletonList(K k){
    return Collections.singletonList(k);
  }
}

Wie bei einer generischen Methode zu erwarten, kann ich anrufendoSomething(K) auf Instanzen vonMyClass mit irgendeinem Gegenstand:

MyClass clazz = new MyClass();
String string = clazz.doSomething("String");
Integer integer = clazz.doSomething(1);

Wenn ich jedoch versuche, Instanzen von zu verwendenMyGenericClass ohne Ich gebe einen generischen Typ an und rufe andoSomething(K) gibt ein zurückObject, egal wasK wurde übergeben in:

MyGenericClass untyped = new MyGenericClass();
// this doesn't compile - "Incompatible types. Required: String, Found: Object"
String string = untyped.doSomething("String");

Seltsamerweise wird es kompiliert, wenn der Rückgabetyp eine generische Klasse ist - z.List<K> (Eigentlich kann dies erklärt werden - siehe Antwort unten):

MyGenericClass untyped = new MyGenericClass();
List<String> list = untyped.makeSingletonList("String"); // this compiles

Es wird auch kompiliert, wenn die generische Klasse eingegeben wird, auch wenn nur Platzhalter verwendet werden:

MyGenericClass<?> wildcard = new MyGenericClass();
String string = wildcard.doSomething("String"); // this compiles

Gibt es einen guten Grund, warum das Aufrufen einer generischen Methode in einer nicht typisierten generischen Klasse nicht funktionieren sollte?

Gibt es einen cleveren Trick in Bezug auf generische Klassen und generische Methoden, den ich vermisse?

BEARBEITEN:

Zur Verdeutlichung würde ich erwarten, dass eine untypisierte oder typisierte generische Klasse die Typparameter der generischen Klasse nicht berücksichtigt (weil sie nicht bereitgestellt wurden). Für mich ist jedoch nicht klar, warum eine untypisierte oder typisierte generische Klasse bedeuten würde, dass generische Methoden nicht berücksichtigt werden.

Es stellt sich heraus, dass dieses Problem bereits auf SO angesprochen wurde, vgl.diese Frage. Die Antworten darauf erklären, dass, wenn eine Klasse untypisiert / in ihrer Rohform ist,alles Generika werden aus der Klasse entfernt - einschließlich der Typisierung generischer Methoden.

Es gibt jedoch keine wirkliche Erklärung, warum dies der Fall ist. Gestatten Sie mir, meine Frage zu klären:

Warum entfernt Java die generische Methodentypisierung für generische Klassen ohne Typ oder ohne Typ? Gibt es einen guten Grund dafür oder war es nur ein Versehen?

EDIT - Diskussion über JLS:

Es wurde vorgeschlagen (als Antwort auf die vorherige SO-Frage und auf diese Frage), dass dies in behandelt wirdJLS 4.8, welche Staaten:

Der Typ eines Konstruktors (§8.8), einer Instanzmethode (§8.4, §9.4) oder eines nicht statischen Felds (§8.3) M eines Rohtyps C, der nicht von seinen Superklassen oder Superschnittstellen geerbt wird, ist der entsprechende Rohtyp zur Löschung seines Typs in der Gattungserklärung entsprechend C.

Mir ist klar, wie das mit einer untypisierten Klasse zusammenhängt - die generischen Klassentypen werden durch die Löschtypen ersetzt. Wenn die Klassengenerika gebunden sind, entspricht der Löschtyp diesen Grenzen. Wenn sie nicht gebunden sind, ist der Löschtyp Objekt - z.

// unbound class types
public class MyGenericClass<T> {
  public T doSomething(T t) { return t; }
}
MyGenericClass untyped = new MyGenericClass();
Object t = untyped.doSomething("String");

// bound class types
public class MyBoundedGenericClass<T extends Number> {
  public T doSomething(T t) { return t; }
}
MyBoundedGenericClass bounded = new MyBoundedGenericClass();
Object t1 = bounded.doSomething("String"); // does not compile
Number t2 = bounded.doSomething(1); // does compile

Während generische Methoden Instanzmethoden sind, ist mir nicht klar, dass JLS 4.8 für generische Methoden gilt. Der Typ der generischen Methode (<K> in einem früheren Beispiel) ist nicht untypisiert, da der Typ durch die Methodenparameter bestimmt wird - nur die Klasse ist untypisiert / typisiert.

Antworten auf die Frage(6)

Ihre Antwort auf die Frage