Java: как написать приведение, которое определяет и суперкласс, и интерфейс?


В моей Java-программе происходит нечто подобное:

void f(Object o) {
    g(o);
}

<T extends MySuperClass & MyInterface> void g(T x) {
    ...;
}

Как я могу бросить o, чтобы это сработало? По-видимому, невозможно указать базовый класс и интерфейс в объявлениях переменных без использования универсальных выражений. Я не думаю, что генераторы будут работать здесь, потому что o создается динамически с помощью отражения, поэтому его фактический класс не известен во время компиляции.

(Да, я знаю, что это странная вещь, чтобы хотеть сделать. Но на самом деле мне нужна функциональность от обоих суперкласс и интерфейс. Я думаю, что я мог бы сделать все проверки типов во время выполнения с instanceof, но это просто кажется таким Java 1.4...)

4 2

4 ответа:

Похоже, что нет никакого способа вызвать" сырой " универсальный метод. Но вы можете создать объект raw-типа (следующее преобразование, очевидно, небезопасно):

void f(Object o) {
    Caster<?> c = new Caster(); 
    g(c.cast(o)); 
}

class Caster<T extends MySuperClass & MyInterface> {
    public T cast(Object o) {
        return (T) o;
    }
}

Вы можете создать новый внутренний класс внутри класса, содержащего f() вызов g()

static abstract class MyCastingClass extends MySuperClass implements MyInterface {}

Тогда вы можете бросить:

 g((MyCastingClass)o);

редактировать:

Однако это, похоже, не работает.

Он позволяет вашему коду компилироваться и не содержит предупреждений, но во время выполнения вы получите ClassCastException, Если ваш объект на самом деле не является экземпляром MyCastingClass

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

Object dest_obj_containing_g = this; // Replace with your object.
Method[] methods = dest_obj_containing_g.getClass().getDeclaredMethods();
for (Method m : methods) {
  if (m.getName().equals("g")) {
    m.invoke(dest_obj_containing_g,o);
    break;
  }
}

Может ли это быть что-то вроде

<T extends MySuperClass implements MyInterface>

Я просто предполагаю здесь...