Al declarar propiedades, métodos y clases en Java, la palabra clave final se puede usar para modificarlo. La variable final es una constante y solo se puede asignar una vez; El método final no puede reescribirse por una subclase; La clase final no puede ser heredada.
1. Miembros finales
Declarar un campo final ayuda al optimizador a tomar mejores decisiones de optimización, porque si el compilador sabe que el valor del campo no cambiará, puede almacenar de forma segura el valor en el registro. El campo final también proporciona un nivel adicional de seguridad al hacer que el compilador obligue al campo a ser de solo lectura.
1.1 Sobre la asignación final de miembros
1) En Java, las variables ordinarias se pueden inicializar de forma predeterminada. Pero las variables del tipo final deben inicializarse explícitamente.
2) Los miembros finales pueden y solo pueden inicializarse una vez.
3) El miembro final debe inicializarse en la declaración (asignando un valor directamente a la variable final cuando se define) o en el constructor, y no se puede inicializar en otro lugar.
Ejemplo 1 Bat.java
Bat de clase pública {final doble pi = 3.14; // Asignar el int I final cuando se define; // Debido a que se debe inicializar en el constructor, la lista de la lista final <bat> no se puede asignar aquí; // porque se debe inicializar en el constructor, BAT () no se puede asignar aquí {i = 100; list = new LinkedList <Bat> (); } Bat (int ii, list <bat> l) {i = ii; list = l; } public static void main (string [] args) {bat b = new Bat (); b.list.add (nuevo Bat ()); // bi = 25; // b.list = new ArrayList <bat) (); System.out.println ("i =" + bi + "tipo de lista:" + b.list.getclass ()); b = nuevo murciélago (23, nueva ArrayList <bat) ()); b.list.add (nuevo Bat ()); System.out.println ("i =" + bi + "tipo de lista:" + b.list.getclass ()); }}
resultado:
I = 100 Tipo de lista: clase java.util.linkedlisti = 23 Tipo de lista: clase java.util.arraylist
Hay dos líneas de declaraciones en el método principal que se comentan. Si elimina el comentario, el programa no podrá compilar. Esto significa que no importa si es el valor de I o el tipo de lista, una vez inicializado, no se puede cambiar. Sin embargo, B puede especificar el valor de I o el tipo de lista reinicializando.
1.2 Inicialización no válida del campo de referencia final
Es un poco problemático usar el campo final correctamente, especialmente para las referencias de objetos cuyos constructores pueden arrojar excepciones. Debido a que el campo final debe inicializarse solo una vez en cada constructor, si el constructor referenciado por el objeto final puede lanzar una excepción, el compilador puede informar un error diciendo que el campo no se ha inicializado. El compilador generalmente es lo suficientemente inteligente como para encontrar que la inicialización en cada rama de dos ramas de código Mutex (por ejemplo, si ... de lo contrario) ocurre solo una vez, pero generalmente no es tan "indulgente" para probar ... los bloques de captura.
El siguiente código generalmente tiene problemas.
class Thingie {public static Thingie getDefaulthingie () {return new Thingie (); }} clase pública foo {rango final privado de finalización; public foo () {try {Thingie = new Thingie (); } catch (Exception e) {Thingie = Thingie.getDefaulthingie (); // Error: el campo final es posible que ya se haya asignado}}}
Puedes modificar esto.
clase pública foo {finales privados y cosa cosa; public foo () {Thingie Temphingie; intente {temptleie = new Thingie (); } Catch (Exception e) {Temphingie = Thingie.getDefaulthingie (); } Thingie = Temphingie; }}
1.3 sobre el uso final de los miembros
Cuando defina una variable en una clase, agregue la palabra clave final ante ella, eso significa que una vez que se inicializa esta variable, no se puede cambiar. El significado de inmutabilidad aquí es que su valor es inmutable para el tipo básico, y su referencia ya no se puede cambiar para la variable del objeto. Sin embargo, los objetos en sí mismos pueden modificarse, y Java no proporciona una forma de hacer que los objetos sean constantes. Esta limitación también encaja en matrices, que son objetos.
Ejemplo 2
Private final int val_one = 9; private static final int val_two = 99; public static final int val_three = 999;
Dado que Val_one y Val_tow son tipos primitivos finales con valores de tiempo de compilación, ambos pueden usarse como constantes de tiempo de compilación y no hay diferencias significativas. Val_three es una forma más típica de definir constantes: definidas como públicas, se puede usar fuera del paquete; definido como estático para enfatizar solo una copia; definido como final para indicar que es una constante.
La variable marcada final se convierte en una constante, pero esta "constante" solo se puede usar dentro de esta clase y no se puede usar directamente fuera de la clase. Sin embargo, cuando usamos Public Static Final para marcar una constante, esta constante se convierte en una constante global (un campo que es estático y final solo ocupa un espacio de almacenamiento que no se puede cambiar). Además, las constantes definidas de esta manera solo se pueden asignar valores cuando se definen, y no se pueden usar en otro lugar.
Ejemplo 3
valor de clase {int i; Valor público (int i) {this.i = i; }} clase pública finalData {private static random rand = new Random (); ID de cadena privada; public FinalData (ID de cadena) {this.id = id; } private final int i4 = rand.nextint (20); static final int i5 = rand.nextint (20); public String toString () {return id + ":" + "i4:" + i4 + ", i5 =" + i5; } public static void main (string [] args) {finalData fd1 = new FinalData ("FD1"); System.out.println (FD1); System.out.println ("Creación de nuevos Datos finales"); FinalData fd2 = new FinalData ("FD2"); System.out.println (FD1); System.out.println (FD2); }}
resultado
FD1: I4: 6, I5 = 3Creating New FinalDatafd1: I4: 6, I5 = 3FD2: I4: 17, I5 = 3
La sección Ejemplos muestra la diferencia entre definir un valor final como estática (I5) y no estática (I4). Esta diferencia solo aparecerá cuando el valor se inicialice durante el tiempo de ejecución, porque el compilador trata el valor compilado por igual. (Y pueden desaparecer de la optimización). Verá esta diferencia cuando ejecute el programa. Tenga en cuenta que en FD1 y FD2, el valor de i5 no se puede cambiar creando un segundo objeto FinalData. Esto se debe a que es estático, que se inicializa en la carga, no cada vez que se crea un nuevo objeto.
Ejemplo 4
valor de clase {int i; Valor público (int i) {this.i = i; }} clase pública ... {valor privado v1 = nuevo valor (11); valor final privado v2 = nuevo valor (22); valor final estático privado v3 = nuevo valor (33); …} Public static void main (string [] args) {... fd1.v2.i ++; // ok-ok-oBject no es constante! fd1.v1 = nuevo valor (9); // ok-no final fd1.v2 = nuevo valor (0); // Error: No se puede cambiar la referencia fd1.v3 = nuevo valor (1); // Error: no puede cambiar la referencia…} Las variables de V1 a V3 ilustran el significado de las referencias finales. Como puede ver en Main (), no puede pensar que no puede cambiar su valor solo porque V2 es definitivo. Dado que es una referencia, final significa que no puede señalar V2 a otro objeto nuevo nuevamente.
Ejemplo 5
clase pública ... {private final int [] a = {1,2,3,4,5,6}; …} Public static void main (string [] args) {... para (int i = 0; i <fd1.a.length; i ++) fd1.a [i] ++; // ok-ok-ok-el objeto no es constante! fd1.a = new int [3]; // Error: no se puede cambiar la referencia ...} Tener el mismo significado para una matriz (puede cambiar su valor, pero no puede señalar a un nuevo objeto), una matriz es otra referencia.
1.4 Resolver las limitaciones de las matrices finales
Aunque las referencias de matriz pueden declararse finales, los elementos de la matriz no pueden. Esto significa que ni las clases que exponen los campos de la matriz final pública o las referencias de devolución a esos campos a través de sus métodos son mutables.
// no inmutable: la matriz de estados podría modificarse mediante un // callerpublicClass DangerousStates {String final privado [] estados = new String [] {"Alabama", "Alaska", "ECT"}; public String [] getStates () {return States; }}
Del mismo modo, aunque una referencia de objeto puede declararse como un campo final, el objeto que hace referencia aún puede ser mutable. Si desea crear un objeto invariante usando el campo final, debe evitar referencias a matrices o objetos mutables para "escapar" de su clase. Para hacer esto sin tener que clonar la matriz repetidamente, una manera fácil es convertir la matriz en una lista.
// Immutable - Devuelve una lista no modificable en su lugar de SafeStates de SafeStates {String final privado [] States = new String [] {"Alabama", "Alaska", "ECT"}; Lista final privada estatales estatales = new AbstractList () {Public Object get (int n) {Return States [n]; } public int size () {return States.length; }}; Lista pública getStates () {return StessAsList; }}
1.5 sobre el uso de parámetros finales
Otro uso es definir el parámetro en el método como final. Para las variables de los tipos básicos, esto no tiene ningún significado práctico, porque las variables de los tipos básicos pasan valores al llamar al método, es decir, puede cambiar la variable de parámetros en el método sin afectar la declaración de llamadas. Sin embargo, para las variables de objetos, es muy práctico porque las variables de objetos se pasan por sus referencias al pasar. De esta manera, su modificación de las variables de objeto en el método también afectará las variables de objeto en la declaración de llamada. Cuando no necesita cambiar las variables del objeto como parámetros en el método, el uso explícitamente de finalización para la declaración le impedirá modificar y afectar involuntariamente el método de llamadas.
1.6 Acerca de las variables de parámetros en las clases internas
Además, cuando se usan variables de parámetros en el método en la clase interna, esta variable de parámetro debe declararse final antes de que pueda usarse.
Ejemplo 6 inclass.java
public class inclass {void InnClass (final String str) {class iClass {iClass () {System.out.println (str); }} Iclass ic = new iClass (); } public static void main (string [] args) {inclass inc = new inclass (); Inc.innerClass ("Hola"); }} 2. Método final
2.1 Uso del método final
1) Para garantizar que el comportamiento de una determinada función permanezca sin cambios durante el proceso de herencia y no se pueda anular, se puede utilizar el método final.
2) Todos los métodos privados y estáticos en la clase son naturalmente finales.
2.2 Palabras clave finales y privadas
Todos los métodos privados en la clase se especifican implícitamente como definitivos. Dado que el método privado no se puede usar, no se puede sobrescribir.
"Anular" solo aparecerá si un método es parte de la interfaz de la clase base. Es decir, un objeto debe poder transformarse hacia arriba en su tipo primitivo y llamar al mismo método. Si un método es privado, no es parte de la interfaz de la clase base. Es solo algún código oculto en la clase, pero con el mismo nombre. Sin embargo, si un método de acceso público, protegido o de paquete se genera de la misma manera en la clase de exportación, el método no producirá el caso "solo con el mismo nombre" que ocurre en la clase base. En este punto, no anuló el método, solo generó un nuevo método. Dado que el método privado no se puede tocar y puede ocultarse efectivamente, nada más debe considerarse excepto por la existencia de la estructura organizativa de la clase a la que pertenece.
3. Clase final
Cuando una clase se define como final, la clase no puede ser heredada. Y debido a que la clase final prohíbe la herencia, todos los métodos en la clase final se especifican implícitamente como finales porque no pueden sobrescribirse.
Final se usa en clases o métodos para evitar que se rompan los vínculos entre los métodos. Por ejemplo, suponga que la implementación de un método de clase X asume que el método M funcionará de alguna manera. Declarar X o M como final evitará que la clase derivada redefine M de esta manera, lo que hace que X funcione de manera anormal. Si bien puede ser mejor implementar X sin estas correlaciones internas, esto no siempre es posible, y el uso final puede evitar futuros cambios incompatibles.
PD: La diferencia entre final, finalmente y finalice