2010-02-10 5 views
4

Учитывая следующий код:Java дженериков и тип стирания

public void example(Object o) { 
    if(o instanceof List<MyType>) 
    //do something 
} 

Я понимаю, что это не представляется возможным (и почему его не представляется возможным), учитывая способ Java обрабатывает дженерики и типа стирания.

Мой вопрос: какой лучший/самый чистый способ достичь этого? Или единственное, что я могу сделать, это проверить, o - List<?>?

+0

Этот вопрос звучит знакомо, как тот, который был задан в течение последних 90 дней или около того. Попробуйте посмотреть [http://stackoverflow.com/questions/1004022/java-generic-class-determine-type]. –

ответ

-3

Возможно, проверив тип объекта во время выполнения, может быть что-то вроде:

if (o.getClass() == List.class) ... 

Очевидно, что вам придется поковыряться в тип класса объекта, чтобы увидеть, если это точное соответствие с List<> и Листом типы элементов.

+0

Во время выполнения класс List точно такой же, как в списке

+1

Видя, что «Список» - это интерфейс, это, вероятно, плохая идея –

0

Не проверяя типы всех элементов в Списке, невозможно определить тип общего параметра в Java, поскольку он существует только во время компиляции и удаляется до выполнения.

Мое предложение было бы, если только вам не нужно, чтобы метод принимал объект (например, соответствовал спецификации интерфейса или переопределял Object.equals), чтобы взять правильный тип, который вы хотите в качестве параметра для метода, и перегрузите метод различными типами, с которыми вам может потребоваться запустить метод.

2

Вы не можете проверить более чем o instanceof List<?>.

Тип безопасности, который вы получаете от Java-дженериков, происходит только во время компиляции. Метод, подобный вашему (который принимает объект, а затем пытается выяснить, что делать), не очень хорошо работает с этим дизайном. я могу понять, почему такой динамический метод необходимо некоторое время, но учтите, дополнив его с версиями для типизированных параметров:

public void example(Object o) { 
    if(o instanceof List<?>) 
    example((List)o); // can only hope that the type is correct here 
} 

public void example(List<MyType> list){ 
    // do something 
} 

В тех случаях, когда те могут быть использованы, вы получите полную выгоду от дженериков. В других случаях вы должны зависеть от людей, читающих ваш Javadoc, и только передачи правильных типов.

То, что даже вышеприведенный подход не может сделать, состоит из двух разных кодов для List<TypeA> и List<TypeB>. Если это действительно необходимо для вас, подумайте о том, чтобы использовать ваши собственные типы оберток ListOfTypeA, ListOfTypeB.

В зависимости от того, что вам нужно сделать, это не может быть даже необходимо смотреть на стертой типа списка в целом, и просто работать на типах времени выполнения отдельных элементов:

for (Object o: list){ 
    if (o instanceof TypeA){ 
    } 
    if (o instanceof TypeB){ 
    } 
} 
0

После компиляции Java стирает информацию о типе для генериков, поэтому вы не можете динамически проверять параметр типа.

Если все пути к этому коду ограничить параметр типа, то делать:

// Return true if object is a list of MyType, false if it is not a list, or is 
// empty 
boolean isListOfMyType(Object o) { 
    if (o instanceof List) { 
     List<?> l = (List<?) o; 
     return (l.size() > 0 && (l.get(0) instanceof MyType) 
    } 
    return true; 
} 

является типизированным, хотя она будет работать только, если список не пуст. Если нет, вам нужно будет изменить приведенное выше, чтобы проверить, проходят ли все элементы testof test (или если они являются нулевыми, если вы разрешаете null в списке).

Другой альтернативой является создание подкласса, который простирается, например, ArrayList<MyType>, и использовать это для вашего instanceof чек.

Последнее, но не менее важное, имеет подкласс, который реализует List<MyType>, позволит вам получить параметр типа с использованием метода Class.getGenericInterfaces(). См. this.

Для любого из этих двух последних методов работы вы должны убедиться, что создание списка всегда создает один из этих типов. То есть. если вызывающий идет и строит свои собственные ArrayList<MyType>, это не сработает.

0

Вопреки общепринятому и редко известному стиранию стилей можно избежать, а это значит, что у вызывающего есть возможность узнать, какие общие параметры использовались во время разговора.

Пожалуйста, обратите внимание на: Using TypeTokens to retrieve generic parameters

Благодарности