2015-11-12 3 views
2

есть проблема с стиранием & Тип вывода. У меня есть следующие иерархии классов, которая не выглядит очень сложным:Вывод на языке Java с стиранием

public class Foo<T> { 

} 

public class Bar<T> { 
    private final Class<T> clazz; 

    public Bar(Class<T> clazz) { 
     this.clazz = clazz; 
    } 
} 

И то, что я пытаюсь сделать, это что-то вроде этого:

Bar<Foo<?>> bar = new Bar<>(Foo.class); 

, который, конечно, не делает работа, поскольку Foo не совсем Foo<?>. Вопрос в том, как построить такой бар? Мне нужно точно Bar<Foo<?>>, а не Bar<Foo>, так как есть метод, который принимает только параметр Bar<Foo<?>>. Цените идеи.

+1

Вы можете наложить 'Foo.class' на' Class > ', что может привести к проблеме, достаточной для ваших целей. (Вы не можете _actually_ представлять разные генерики только с объектами класса.) –

ответ

1

Вы не можете создать общий объект без предоставления информации о типе в <>, как показано в сообщении вопроса. Вы должны указать тип или использовать версию raw. Если вы вынуждены использовать дикий тип параметров карты, а затем просто подавить предупреждение с помощью сырого типа, как показано ниже

@SuppressWarnings("rawtypes") 
Bar<Foo<?>> bar = new Bar(Foo.class);  

//Bar is having no type "<>" (but this is not recommended 
+1

Верно, я не получил точку вашего ответа изначально. Это примерно так же корректно, как и более сложное предложение. –

+1

Это вариант, я полагаю. Интересно, почему я сам не пробовал :) Thx! – Stas

3

К сожалению, такого объекта Class нет, потому что, как вы заметили, стирание означает, что не может быть. Вы должны бросить его:

((Class<Foo<?>>)(Class)Foo.class) 

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

Двойной литой необходим, поскольку компилятор знает, что Foo.class несовместим с Class>, поэтому вы должны сначала перенести его в «сырой» тип. Класс: использование необработанных типов в выражении отключает общий набор компилятора -type проверяет это выражение, поэтому «невозможное» выполнение работает нормально.

0

С java.lang.Class неизменен, вы могли бы использовать более слабое объявление типа в конструктор Bar:

class Foo<T> {} 

class Bar<T> { 
    private final Class<? extends T> clazz; 

    public Bar(Class<? extends T> clazz) { 
     this.clazz = clazz; 
    } 
} 

Если вы все еще нуждаются в поле, чтобы иметь тип Class<T>, а не Class<? extends T> это безопасно, чтобы бросить его в конструкторе.