Окончательные аргументы в методах интерфейса - какая точка?
В Java вполне логично определять аргументы final
в методах интерфейса и не подчиняться этому в классе реализации, например:
public interface Foo {
public void foo(int bar, final int baz);
}
public class FooImpl implements Foo {
@Override
public void foo(final int bar, int baz) {
...
}
}
В приведенном выше примере bar
и baz
имеют противоположные определения final
в классе VS интерфейса.
Таким же образом, ограничения final
не применяются, когда один метод класса расширяет другой, либо abstract
, либо нет.
Хотя final
имеет практическое значение внутри тела метода класса, существует ли какая-либо точка, указывающая final
для параметров интерфейса интерфейса?
Ответы
Ответ 1
Похоже, в этом нет никакого смысла. Согласно спецификации языка Java 4.12.4:
Объявление переменной final может служить полезной документацией, что ее значение не изменится и поможет избежать ошибок программирования.
Однако final
модификатор параметра метода не упоминается в правилах сопоставления подписей переопределенных методов, и он не влияет на вызывающую функцию, только в теле реализации. Кроме того, как отметил Робин в комментарии, final
модификатор параметра метода не влияет на сгенерированный байт-код. (Это не относится к другим видам использования final
.)
Ответ 2
Некоторые IDE будут копировать сигнатуру абстрактного/интерфейсного метода при вставке реализующего метода в подкласс.
Я не верю, что это имеет какое-либо значение для компилятора.
РЕДАКТИРОВАТЬ: Хотя я считаю, что это было правдой в прошлом, я не думаю, что текущие IDE делают это больше.
Ответ 3
Заключительные аннотации параметров метода всегда относятся только к реализации метода никогда не вызывающему. Поэтому нет реальной причины использовать их в сигнатурах интерфейса. Если вы не хотите следовать тому же самому стандарту кодирования, который требует окончательных параметров метода, во всех сигнатурах методов. Тогда приятно иметь возможность сделать это.
Ответ 4
Обновление: Оригинальный ответ ниже был написан без полного понимания вопроса и поэтому прямо не затрагивает вопрос :)
Тем не менее он должен быть информативным для тех, кто хочет понять общее использование final
.
Что касается вопроса, я хотел бы привести свой собственный комментарий ниже.
Я считаю, что вы не обязаны реализовывать окончательность аргумента, чтобы дать вам свободу решать, должно ли оно быть окончательным или нет в вашей собственной реализации.
Но да, это звучит довольно странно, что вы можете объявить его final
в интерфейсе, но при этом он не является окончательным в реализации. Это имело бы смысл, если бы:
Ключевое слово a. final
не разрешено для интерфейсных (абстрактных) аргументов метода (но вы можете использовать его в реализации) или
b. объявление аргумента как final
в интерфейсе заставит его объявить final
в реализации (но не принудительно для нефиналов).
Я могу представить две причины, по которым сигнатура метода может иметь параметры final
: Beans и Объекты (На самом деле, они являются одной и той же причиной, но несколько разных контекстов.)
Объекты:
public static void main(String[] args) {
StringBuilder cookingPot = new StringBuilder("Water ");
addVegetables(cookingPot);
addChicken(cookingPot);
System.out.println(cookingPot.toString());
// ^--- OUTPUT IS: Water Carrot Broccoli Chicken ChickenBroth
// We forgot to add cauliflower. It went into the wrong pot.
}
private static void addVegetables(StringBuilder cookingPot) {
cookingPot.append("Carrot ");
cookingPot.append("Broccoli ");
cookingPot = new StringBuilder(cookingPot.toString());
// ^--- Assignment allowed...
cookingPot.append("Cauliflower ");
}
private static void addChicken(final StringBuilder cookingPot) {
cookingPot.append("Chicken ");
//cookingPot = new StringBuilder(cookingPot.toString());
// ^---- COMPILATION ERROR! It is final.
cookingPot.append("ChickenBroth ");
}
Ключевое слово final
гарантировало, что мы случайно не создадим новый локальный кулинарный горшок, показывая ошибку компиляции, когда мы попытаемся это сделать. Это обеспечило добавление куриного бульона в наш оригинальный горшок для приготовления пищи, который получил метод addChicken
. Сравните это с addVegetables
, где мы потеряли цветную капусту, потому что она добавила, что в новый локальный кулинарный горшок вместо исходного банка, который он получил.
Beans:
Это та же концепция, что и объекты (как показано выше). Beans по существу Object
в Java. Однако Beans (JavaBeans) используются в различных приложениях как удобный способ хранения и передачи определенного набора связанных данных. Так же, как addVegetables
может испортить процесс приготовления пищи, создав новый кухонный горшок StringBuilder
и выбросив его с помощью цветной капусты, он также может сделать то же самое с кулинарным вареном JavaBean.
Ответ 5
Я считаю, что это может быть излишняя деталь, так как окончательный или нет - деталь реализации.
(похоже, как объявление методов/членов в интерфейсе как общедоступное.)