Группа захвата дженериков Java

У меня проблемы с правильным использованием групп захвата Java.

Предположим, у меня есть эти классы:

class Foo{}
class Bar{}

interface InterfaceXYZ<T>{ 
  void doSomething(T t);
}

class FooImplementation implements InterfaceXYZ<Foo>{
  @Override void doSomething(Foo){}
}

В заключение,

class Delegator<T>{
  Delegator(InterfaceXYZ<T> delegate){this.delegate = delegate;}

  void doSomething(T t) {
    delegate.doSomething(t);
  }

  private InterfaceXYZ<T> delegate;
}

Проблема в том, что это работает нормально -

FooImplementation fi = new FooImplementation();
Delegator d = new Delegator(fi);
d.doSomething(new Foo());

Это не работает нормально (как и ожидалось) - вызывает исключение во время выполнения

FooImplementation fi = new FooImplementation();
Delegator d = new Delegator(fi);
d.doSomething(new Bar());

Почему не выдает ошибку времени компиляции? Если мне нужно, чтобы он выдавал ошибку времени компиляции, какие изменения мне нужно сделать?

1 ответ

Решение

По большей части это правильно, но вам нужно указать часть <...> во время создания экземпляра (или она будет по умолчанию иметь тип raw, что аналогично . См. Этот ответ для получения подробной информации о разнице между raw, и ). И Foo, и Bar оба являются объектами, поэтому компилятор видит это и думает, что все в порядке.

Вот как выглядит экземпляр с использованием <...>. Вот, InterfaceXYZ<Foo> и FooImplementation являются взаимозаменяемыми (поскольку компилятор знает, что FooImplementation является InterfaceXYZ<Foo>)

Для Фу

InterfaceXYZ<Foo> fi = new FooImplementation();
Delegator<Foo> d = new Delegator<Foo>(fi);
d.doSomething(new Foo());

И для Bar (получение ошибки времени компиляции вместо времени выполнения)

InterfaceXYZ<Bar> fi = new FooImplementation();
Delegator<Bar> d = new Delegator<Bar>(fi);
d.doSomething(new Bar());

Дополнительное примечание:

InterfaceXYZ<?> fi = new FooImplementation(); не будет выдавать ошибку времени компиляции, потому что вы можете сказать добавить фи к List<InterfaceXYZ<?>>, где InterfaceXYZ<bar> также действителен и пригоден для использования. Компилятор не может и не будет проверять все возможные способы использования объекта в стеке вызовов, поэтому доверяйте только ошибкам времени компиляции, которые появляются только в контексте текущего компилируемого класса.

Другие вопросы по тегам