Обобщения Java: почему someObject.getClass () не возвращает Class? - PullRequest
12 голосов
/ 16 декабря 2010

Я бы ожидал, что с точки зрения времени компиляции, а также с точки зрения времени выполнения для .getClass() не будет проблемой обеспечить правильное тип возвращаемого значения.

Но я долженбыть неправым.

public class _GetClassGenerics2 {

  static class MyClass {
  }

  public static void main(String[] args) {
    MyClass myInstance = new MyClass();
    // here it works
    Class<? extends MyClass> type = myInstance.getClass();

    myMethod(myInstance);
  }

  public static <T extends MyClass> void myMethod(T instance) {
    Class<? extends T> type = instance.getClass();
// java.lang.RuntimeException: Uncompilable source code - incompatible types
//  required: java.lang.Class<? extends T>
//  found:    java.lang.Class<capture#1 of ? extends _GetClassGenerics2.MyClass>
  }

}

РЕДАКТИРОВАТЬ: Это не работает с Class<T> и Class<? super T> либо.

Ответы [ 4 ]

6 голосов
/ 16 декабря 2010

java.lang.Class не представляет тип (используйте java.lang.reflect.Type для этого). Если бы T было бы, скажем, ArrayList<String>, тогда не было бы смысла в том, чтобы быть Class<ArrayList<String>>.

Стоит отметить, что в этом конкретном случае нет необходимости для метода быть универсальным.

public static <T extends MyClass> void myMethod(T instance) {

Эквивалентно:

public static void myMethod(MyClass instance) {
3 голосов
/ 16 декабря 2010

Согласно Javadoc метода getClass :

Фактический тип результата: Class<? extends |X|>, где | X | это стирание статического типа выражения на котором getClass называется. За Например, в этом акте не требуется фрагмент кода

Здесь значение |X| в вашем фрагменте кода равно MyClass, следовательно, instance.getClass() можно назначить только Class<? extends MyClass> или Class<?>.

Причина этой конкретной формулировки заключается в том, что когда вы говорите, что для этой переменной, имеющей тип T, где <T extends MyClass>, может быть несколько классов, которые расширяют MyClass и, следовательно, способны удовлетворять критериям T extends MyClass. Без информации времени выполнения невозможно узнать, какой конкретный подкласс реализации MyClass был передан в метод. Следовательно, чтобы обеспечить общее решение, он возвращает <? extends MyClass>, поскольку это будет выполняться для любого подкласса MyClass независимо от того, в какой экземпляр класса передается.

0 голосов
/ 16 декабря 2010

вместо

Class<? extends T> type = instance.getClass();

вам нужно использовать

Class<? extends MyClass> type = instance.getClass();

Вы не можете напрямую использовать T здесь.

Причиной является сигнатура метода Object.getClass() (которую вы вызываете). Это:

public final Class<? extends Object> getClass()

Итак, вы пытаетесь конвертировать из Class<? extends Object> в Class<? extends T>, что недопустимо (потому что вы понижаете) допускается , допускается использование явного приведения:

Class<? extends T> type = (Class<? extends T>) instance.getClass();

будет работать (хотя генерирует предупреждение о безопасности типа).

0 голосов
/ 16 декабря 2010

Java не поддерживает универсальный тип , например,

Объект может реализовать

class Object {
    Class<this> getClass()
}

Но у getClass () нет способа выразить, что он вернет тип, который является классом объекта. Компилятор также не понимает, что делает этот метод.

ИМХО, такое поведение должно было поддерживаться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...