2014-11-19 3 views
1

У меня есть метод, который возвращает компонент (объект, который расширяет компонент интерфейс) экземпляр по типу (классу).Непроверенные дженерики или бокс объекта?

Каков наилучший или правильный способ возврата компонента? Использование нечетных генериков или возвращаемого компонента как Компонент. Или есть лучший способ, чем эти два я узнал? На самом деле я хотел бы получить компонент по типу возврата, указанному в инструкции (например, ConcreteComponent cc = this.getComponent(););

@SuppressWarnings("unchecked") 
public <T> T getComponent(final Class<? extends T> type) { 
    for (Component c : this.components) { 
     if (c.getClass().isAssignableFrom(type)) { return (T) c; } 
    } 
    return null; 
} 

public Component getComponent2(final Class<? extends Component> type) { 
    for (Component c : this.components) { 
     if (c.getClass().isAssignableFrom(type)) { return c; } 
    } 
    return null; 
} 

ответ

5

У вас возникла логика Class.isAssignableFrom().

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

public <T extends Component> T getComponent(Class<T> type) { 
    for (Component c : this.components) { 
     if (type.isAssignableFrom(c.getClass())) { 
      return type.cast(c); 
     } 
    } 
    return null; 
} 

Примечания:

  1. Это контрпродуктивно использовать подстановочный знак в параметре типа для аргумента type. Использование общего метода уже дает вам всю необходимую гибкость и может помочь вам избежать необходимости использования явного параметра типа при вызове функции.
  2. Class.cast() является типичной альтернативой литеровочному литье. Вы можете быть в состоянии обойтись без пресечения предупреждений о безопасности типа, если вы его используете.
  3. Вы не можете получить фактический класс выбранного компонента в качестве формального типа возврата метода, потому что этот класс не может быть известен во время компиляции. (Я не уверен, были ли вы на самом деле просят за это, но это звучало, как, возможно, вы были.)
+2

'type.isAssignableFrom (c.getClass())' также может быть 'type.isInstance (c)'. – Radiodef

+0

@Radiodef - хорошая точка и 'isInstance()', вероятно, лучший выбор для этого, но это не позволяет мне исправить использование Mato 'isAssignableFrom()'. –

0

Во-первых, я не верю, что ConcreteComponent cc = this.getComponent(); возможно в Java в это время. Это потребовало бы вычисления класса объекта назад, и это не представляется возможным.

Я бы порекомендовал это: он использует Class.cast(), который избегает предупреждения, а также очищает бит generics (пропускает ненужный шаблон и указывает, что он расширяет компонент).

public <T extends Component> T getComponent(final Class<T> type) { 
    for (Component c : this.components) { 
     if (c.getClass().isAssignableFrom(type)) { 
      return type.cast(c); 
     } 
    } 
    return null; 
} 
Смежные вопросы