Java: как написать приведение, которое определяет и суперкласс, и интерфейс?
В моей Java-программе происходит нечто подобное:
void f(Object o) {
g(o);
}
<T extends MySuperClass & MyInterface> void g(T x) {
...;
}
Как я могу бросить o, чтобы это сработало? По-видимому, невозможно указать базовый класс и интерфейс в объявлениях переменных без использования универсальных выражений. Я не думаю, что генераторы будут работать здесь, потому что o создается динамически с помощью отражения, поэтому его фактический класс не известен во время компиляции.
(Да, я знаю, что это странная вещь, чтобы хотеть сделать. Но на самом деле мне нужна функциональность от обоих суперкласс и интерфейс. Я думаю, что я мог бы сделать все проверки типов во время выполнения с instanceof, но это просто кажется таким Java 1.4...)
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; } }