Данный вопрос возник из-за спо... дискуссии с коллегой, что именно предпочтительнее. Есть код, который можно записать двумя способами:
1 Способ:
public interface MyInterface<T> {
T function(T prm);
}
и
2 Способ:
public interface MyInterface {
<T> T function(T prm);
}
Реализация интерфейса один класс MyInterfaceImpl (так же с Generic у класса или метода), класс создается с помощью Spring DI
в конструкторах классов, то есть:
1 Способ:
public class OtherClass {
private final MyInterface<String> str;
@Inject
public OtherClass(MyInterface<String> str) {
this.str = str;
}
2 Способ:
public class OtherClass {
private final MyInterface str;
@Inject
public OtherClass(MyInterface str) {
this.str = str;
}
В принципе сама по себе реализация обоими способами не проблема. Вопрос в правильности, плюсах и минусах каждого подхода. Если сможете приведите цитаты Oracle документации или известных авторов по этому вопросу (я пока не нашел хороших).
Если вы хотите чтобы класс который будет наследовать Ваш интерфейс работал только с одним типом тогда MyInterface<T>
подходит больше, так как крайне не удобно будет использовать дженерик методы если класс будет работать только с одним типом, Вам надо будет каждый раз явно указать тип с помощью <T>
Но если вы хотите чтобы класс который будет наследовать Ваш интерфейс работал с разными типами тогда лучше пользоваться дженерик методами.
Хорошим примером будет java.util.List
. В нем есть методы который используют тип дженерика (boolean add(E e);
, E set(int index, E element);
), и дженерик методы (<T> T[] toArray(T[] a);
) и и другие.
И так, и так правильно, вы должны смотреть на то, какой смысл вашего класса.
Например, если у вас есть универсальный завод по производству оружия, то у вас он один, а типов оружия может производить много:
public class WeaponFactory {
public <T extends Weapon> T produce() { ... }
}
А если у вас станок, который выпускает один тип оружия, то этот тип — «параметр» самого станка, и его разновидность выпускаемого оружия предпределена:
public class WeaponMachine<T extends Weapon> {
public T make() { ... }
}
Смотрите на семантику ваших классов.