2013-07-03 2 views
0

У меня есть метод, похожий на этот.Как получить <? super T> от T

static <T> void doSomethind(final Class<? super T> type, final T instance) { 

} 

И есть способ поиска соответствующего суперкласса для T или Object.

static Class<?> getType(final Object instance) { 

    // returns a Class which is parent of given instance. 
} 

Я даже не уверен, что <? super T> часть необходимо или нет. Может это <T>?

static void doSomething(final Object instance) { 

    final Class<?> type = getType(instance); 

    // how can I call <T>doSomething(Class<T>, t)? 
} 

Или

static <T> void doSomething(final T instance) { 

    final Class<?> type = getType(instance); 

    // how can I call <T>doSomething(Class<T>, t)? 
} 

Вопрос в том, как я могу назвать doSomething(Class, Object) метод?

UPDATE

мне так жаль. Но я даже не знаю, что я прошу. Поэтому я решил рассказать глупую (полную) историю.

В javax.xml.bind.Marshaller, есть способы выглядеть marshal(Object, XXX), такие как

  1. маршала (Object, ContentHandler)
  2. маршала (Object, File)
  3. и так далее.

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

public static <T> marshal(Marshaller marshaller, Object element, 
          Class<? super T> targetType, T target) 
    throws VariousNastyExceptions { 

    // like a boss, huh? 
    Marshaller.class.getMethod("marshal", Object.class, targetType) 
     .invoke(marshaller, element, target); 
} 

// still not sure about <? super T> 

Так что каждый может ссылаться именно так.

marshal(marshaller, element, OutputStream.class, output); 
// say output is an instance of ByteArrayOutputStream 

marshal(marshaller, element, Result.class, result); 
// say the result is an instance of StreamResult 

А потом я хочу новую версию без targetType.

Для этого я, во-первых, собрал этих кандидатов для targetType.

// InputStream.class, File.class, XMLEventWriter.class, and so on. 
static final List<Class<?>> TARGET_TYPES; 
static { 
    final List<Class<?>> targetTypes = new ArrayList<Class<?>>(); 
    for (Method method : Marshaller.class.getMethods()) { 
     // if method is for marshal(Object, T) // code skipped 
     targetTypes.add(method.getParameterTypes()[0]); 
    } 
    TARGET_TYPES = Collections.unmodifiableList(targetTypes); 
} 

Теперь я могу принести targetType от данного Object.

static Class<?> getTargetType(Object target) { 

    for (Class<?> targetType : TARGET_TYPES) { 
     if (targetType.isAssignableFrom(target.getClass())) { 
      return targetType; 
     } 
    } 

    return null; // don't count this for now 
} 

И я, наконец, попытался

// do I need a <T> here? 
static void marshal(Marshaller marshaller, Object element, Object target) { 

    final Class<?> targetType = getTargetType(target); 

    // compiler hates this statement 
    marshal(marshaller, element, targetType, target); 
} 

Я просто хочу Cipher для дешифрования следующего сообщения.

method Marshallers.<T> marshal(Marshaller,Object,Class<? super T>, T) is not applicable 
(actual argument Class <CAP#1> cannot be converted to Class<? super Object> by method 
    invocation conversion) 

Я думаю, что смогу это сделать.

static <T> void marshal(Marshaller marshaller, Object element, T target) { 

    // No ClassCastException guaranteed 
    @SuppressWarnings("unchecked") 
    final Class<? super T> targetType = 
     (Class<? super T>) getTargetType(target); 

    marshal(marshaller, element, targetType, target); 
} 

Есть ли лучший способ?

+1

Я не думаю, что есть лучший способ. При объединении «продвинутых» дженериков с Reflection вы можете быть счастливы, что он работает вообще. ;) – ssindelar

+0

Я даже не знаю, какой ответ я должен принять. Тем не менее все проголосовали. –

ответ

1

На самом деле вы не можете без предупреждения. Вам нужно использовать небезопасный бросок.

static <T> void doSomething(final Class<T> type, final T instance) 
{ 
} 

//here the unchecked cast warning can be suppressed. 
//It could be somewhere else though, the unchecked cast I mean. This is one solution only. 
@SuppressWarnings("unchecked") 
static <T> Class<T> getType(final T instance) 
{ 
    return (Class<T>) instance.getClass(); 
} 

static <T> void doSomething(final T instance) 
{ 
    final Class<T> type= getType(instance); 
    //call to doSomething with a type and an instance 
    doSomething(type, instance); 
} 
+1

Вы можете сделать это без опасного броска. Как вы можете видеть в ответах ниже. – darijan

+0

Нет, вы не можете. Ответы ниже просто исключают реализацию getType() ... –

1

Дженерики с «<? super E>» всегда немного сложны, и я всегда нашел способ обойти его. Может быть, вы можете это сделать.

Я не совсем то, что вы хотите сделать, но что произойдет, если вы попытаетесь позвонить?

doSomething(String.class, "foo"); 

С <? super T> вы также можете сделать:

doSomething(Object.class, "foo"); 

Это не было бы возможно только с классом.

1

Это должно сделать вашу боль уйти

//a target method to call 
static <T> void doSomething(final Class<? super T> type, final T instance) { 
} 

//returns a super of T as you pointed out 
static <T> Class<? super T> getType(final T instance) { 
} 

static <T> void doSomething(final T instance) { 
    final Class<? super T> type= getType(instance); 
    //call to doSomething with a type and an instance 
    doSomething(type, instance); 
} 
2

Можете ли вы объяснить, почему вам нужно что-то вроде этого?

Но для вызова метода doSomething (класса, объекта) вы можете изменить метод getType следующим образом;

static <T> Class<? super T> getType(final T instance) { 
// returns a Class which is parent of given instance. 
} 

static void invokeDoSomething(){ 
     A instance = new A(); 
     Class<? super A> type = getType(instance); 
     doSomethind(type, instance); 
    } 
Смежные вопросы