Ogólne metody Java w klasach generycznych

Jeśli utworzysz klasę ogólną w Javie (klasa ma ogólne parametry typu), czy możesz użyć metod ogólnych (metoda przyjmuje ogólne parametry typu)?

Rozważ następujący przykład:

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);
  }
}

Jak można się spodziewać po ogólnej metodzie, mogę zadzwonićdoSomething(K) na przykładachMyClass z dowolnym obiektem:

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

Jeśli jednak spróbuję użyć instancjiMyGenericClass bez określając rodzaj ogólny, dzwoniędoSomething(K) zwracaObject, niezależnie od tego, coK został przekazany:

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

Co dziwne, kompiluje się, jeśli typem zwracanym jest klasa ogólna - np.List<K> (Właściwie można to wyjaśnić - patrz odpowiedź poniżej):

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

Ponadto kompiluje się, jeśli typowa klasa jest wpisana, nawet jeśli tylko z symbolami wieloznacznymi:

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

Czy istnieje dobry powód, dla którego wywołanie metody ogólnej w nietypowej klasie ogólnej nie powinno działać?

Czy istnieje sprytna sztuczka dotycząca klas ogólnych i metod ogólnych, których brakuje?

EDYTOWAĆ:

Aby to wyjaśnić, oczekiwałbym, że klasa ogólna typu beztypowego lub typu surowego nie będzie honorować parametrów typu klasy ogólnej (ponieważ nie zostały dostarczone). Jednak nie jest jasne dla mnie, dlaczego nietypowa lub typowa klasa generyczna oznaczałaby, że ogólne metody nie są honorowane.

Okazuje się, że kwestia ta została już poruszona w sprawie SO, c.f.to pytanie. Odpowiedzi na to wyjaśniają, że gdy klasa jest bez typu / w swojej surowej postaci,wszystko leki generyczne są usuwane z klasy - w tym typowanie metod ogólnych.

Jednak tak naprawdę nie ma wyjaśnienia, dlaczego tak się dzieje. Pozwólcie, że wyjaśnię moje pytanie:

Dlaczego Java usuwa ogólną metodę wpisując na klasach ogólnych typu beztypowego lub surowego? Czy jest ku temu dobry powód, czy tylko przeoczenie?

EDIT - dyskusja na temat JLS:

Zasugerowano (w odpowiedzi na poprzednie pytanie SO i na to pytanie), że jest to traktowaneJLS 4.8, który stwierdza:

Typ konstruktora (§8.8), metoda instancji (§8.4, §9.4) lub pole niestatyczne (§ 8.3) M surowego typu C, który nie jest dziedziczony z nadklas lub superinterfejsów, jest typem surowym, który odpowiada do wymazania tego typu w ogólnej deklaracji odpowiadającej C.

Jest dla mnie jasne, jak odnosi się to do klasy bez typu - typy generyczne klasy są zastępowane typami wymazywania. Jeśli klasy generyczne są powiązane, to typ wymazywania odpowiada tym ograniczeniom. Jeśli nie są związane, to typem wymazywania jest Obiekt - np.

// 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

Chociaż metody ogólne są metodami instancji, nie jest dla mnie jasne, czy JLS 4.8 ma zastosowanie do metod ogólnych. Rodzaj metody ogólnej (<K> we wcześniejszym przykładzie) nie jest bez typu, ponieważ jego typ jest określony przez parametry metody - tylko klasa jest bez typu / surowo wpisana.

questionAnswers(6)

yourAnswerToTheQuestion