Argumentos finales en métodos de interfaz: ¿cuál es el punto?

En Java, es perfectamente legal definir argumentos final en métodos de interfaz y no obedecer eso en la clase implementadora, por ejemplo:

 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) { ... } } 

En el ejemplo anterior, bar y baz tiene las definiciones final opuestas en la clase VS de la interfaz.

De la misma manera, no se aplican restricciones final cuando un método de clase se extiende a otro, ya sea abstract o no.

Mientras que el valor final tiene algún valor práctico dentro del cuerpo del método de clase, ¿hay algún punto que especifique el final para los parámetros del método de interfaz?

No parece que sea así. De acuerdo con la Especificación del lenguaje Java 4.12.4 :

Declarar una variable final puede servir como documentación útil de que su valor no cambiará y puede ayudar a evitar errores de progtwigción.

Sin embargo, un modificador final en un parámetro de método no se menciona en las reglas para hacer coincidir firmas de métodos reemplazados, y no tiene ningún efecto en el llamador, solo dentro del cuerpo de una implementación. Además, como observó Robin en un comentario, el modificador final en un parámetro de método no tiene efecto en el código de bytes generado. (Esto no es cierto para otros usos de final ).

Algunos IDEs copiarán la firma del método abstracto / interfaz al insertar un método de implementación en una subclase.

No creo que haga ninguna diferencia para el comstackdor.

Las anotaciones finales de los parámetros del método siempre son solo relevantes para la implementación del método, nunca para la persona que llama. Por lo tanto, no hay una razón real para usarlos en las firmas de métodos de interfaz. A menos que desee seguir el mismo estándar de encoding consistente, que requiere parámetros de método finales, en todas las firmas de métodos. Entonces es bueno poder hacerlo.

Actualización: la respuesta original a continuación fue escrita sin entender completamente la pregunta, y por lo tanto no aborda directamente la pregunta :) Sin embargo, debe ser informativo para aquellos que buscan entender el uso general de final palabra clave final .

En cuanto a la pregunta, me gustaría citar mi propio comentario de abajo.

Creo que no estás obligado a implementar la finalidad de un argumento para dejarte libre para decidir si debe ser final o no en tu propia implementación.

Pero sí, parece bastante extraño que puedas declararlo como final en la interfaz, pero que no sea definitivo en la implementación. Hubiera tenido más sentido si cualquiera de los dos:

a. No se permitió la palabra clave final para los argumentos del método de interfaz (abstracto) (pero puede usarlo en la implementación), o
segundo. declarar un argumento como final en la interfaz lo forzaría a declararse final en la implementación (pero no forzado para los no finales).


Puedo pensar en dos razones por las que una firma de método puede tener parámetros final : Frijoles y Objetos ( En realidad, ambos son la misma razón, pero contextos ligeramente diferentes ) .

Objetos:

 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 "); } 

La palabra clave final aseguró que no crearemos accidentalmente una nueva olla de cocina local al mostrar un error de comstackción cuando intentamos hacerlo. Esto aseguró que el caldo de pollo se agregue a nuestra olla de cocina original que addChicken método addChicken . Compare esto con las addVegetables en las que perdimos la coliflor porque la agregó a una olla de cocina local nueva en lugar de la olla original que obtuvo.

Frijoles: es el mismo concepto que los objetos (como se muestra arriba) . Los frijoles son esencialmente Object en Java. Sin embargo, los beans (JavaBeans) se utilizan en diversas aplicaciones como una forma conveniente de almacenar y pasar una colección definida de datos relacionados. Del mismo modo que addVegetables podría estropear el proceso de cocción al crear una nueva olla StringBuilder y tirarla con la coliflor, también podría hacer lo mismo con una olla de cocina JavaBean .

Creo que puede ser un detalle superfluo, ya sea si es definitivo o no, es un detalle de implementación.

(Algo así como declarar métodos / miembros en una interfaz como públicos).