2012-04-26 10 views
46

El siguiente código en Java usa una matriz final de String y no hay duda al respecto.matriz final en Java

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Muestra la siguiente salida en la consola.

I can never change 

El siguiente código también va sin ninguna duda.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    //CONSTANT_ARRAY={"I", "can", "never", "change"}; //Error - can not assign to final variable CONSTANT_ARRAY. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

Obviamente, la línea comentada hace que el error especificado porque estamos tratando de volver a asignar el declarada final matriz de tipo String.


¿Qué pasa con el siguiente código.

final public class Main { 
    public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"}; 

    public static void main(String[] args) { 
    CONSTANT_ARRAY[2] = "always"; //Compiles fine. 
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) { 
     System.out.print(CONSTANT_ARRAY[x] + " "); 
    } 
    } 
} 

y muestra I can always change significa que podríamos administrar para modificar el valor de la final matriz de tipo String. ¿Podemos modificar la matriz completa de esta manera sin violar la regla de final?

Respuesta

75

final en Java afecta a la variable , no tiene nada que ver con el objeto que le está asignando.

final String[] myArray = { "hi", "there" }; 
myArray = anotherArray; // Error, you can't do that. myArray is final 
myArray[0] = "over"; // perfectly fine, final has nothing to do with it 

Editar para añadir de: Tenga en cuenta que he dicho objeto que está asignando a ella. En Java, una matriz es un objeto. Esto mismo se aplica a cualquier otro objeto:

final List<String> myList = new ArrayList<String>(): 
myList = anotherList; // error, you can't do that 
myList.add("Hi there!"); // perfectly fine. 
+3

Dijiste _object_, y eso es bueno Esto se aplica a todos los objetos, no sólo matrices Está bien para modificar los objetos que se encuentran.. el valor de las variables finales también. Por ejemplo, 'final List list = new ArrayList (); list.add (" foo ");'. –

9

Solo puede hacer que la referencia de matriz no pueda modificarse. Si desea que los elementos no se puedan cambiar, debe usar una colección no modificable de algún tipo.

3

Cuando se declara una matriz como final, puede cambiar los elementos de la matriz, sin embargo no se puede cambiar la referencia de esta matriz.

+1

Gracias por la simple explicación de una línea. – napender

1

El valor de la variable CONSTANT_ARRAY no puede cambiar. Esa variable contiene una matriz (referencia a una). Sin embargo, el contenido de la matriz puede cambio. Lo mismo sucede cuando declara cualquier tipo de variable final que no sea un tipo escalar simple (por ejemplo, un objeto).

Tenga cuidado al nombrar sus variables. :-) Llamarlo CONSTANT_ARRAY no hace que el contenido de la matriz sea incambiable.

Aquí es una buena referencia: The final word on final

2

definitiva sólo garantiza la inmutabilidad de primitivas. Y también garantiza que una variable se asigna solo una vez. Si un objeto es mutable, puede cambiar el contenido del evento definido como final. Puede consultar colecciones inmutables para sus necesidades. Tal como Collections.unmodifiableList() http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)

+2

¿No implica la segunda frase el primero? – delnan

+0

No. una variable puede hacer referencia a una referencia de objeto, no necesariamente un prim itivo – afsina

+1

Sí, ¿y qué? Las variables son variables, no importa si son de tipo primitivo o de tipo de referencia. Y en cualquier caso, no puede ser reasignado. – delnan

13

Está malinterpretando la implementación final.final se aplica a la referencia de objeto de matriz, lo que significa que una vez que se inicia, la referencia nunca puede cambiar, pero la matriz puede ser poblada. "No está infringiendo las reglas", ha especificado solo una regla sobre el cambio de referencia que funciona en consecuencia. Si desea que los valores también deben nunca cambiar hay que ir por listas inmutables, es decir

List<String> items = Collections.unmodifiableList(Arrays.asList("I", "can", "never", "change")); 
2

La referencia al objeto de matriz es definitiva (no se puede cambiar por ejemplo, en caso de que le intente asociar una matriz java objeto diferente (instancia de String []) a la misma variable final ... obtendría un error de tiempo de compilación.

PERO los campos del objeto de matriz final en su ejemplo no son definitivos, por lo que puede modificar su valor. ... mientras que el objeto Java que creó, CONSTANT_ARRAY, después de recibir un valor inicial, tendrá ese valor "para siempre" == hasta que se detenga la JVM. :) Será la misma instancia de String Array "para siempre".

Las variables finales en Java no son un gran problema, solo dedique un tiempo a digerir el tema/idea cuidadosamente. :-)
sugiero a todos aquellos que no están seguros de meditar sobre esta página, por ejemplo: https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

Cito la parte respectiva:

" Una vez que una variable final ha sido asignado, siempre contiene el mismo valor. Si una variable final contiene una referencia a un objeto, entonces el estado del objeto puede cambiarse por operaciones en el objeto, pero la variable siempre se referirá al mismo objeto.

Esto se aplica también a las matrices, porque las matrices son objetos; si una variable final contiene una referencia a una matriz, los componentes de la matriz pueden modificarse mediante operaciones en la matriz, pero la variable siempre se referirá a la misma matriz. "

0
final int[] res; 
    int[] res1; 
    int[] res2 = new int[1]; 
    res2[0]=20; 

    res1=res2; 
    res1=res2;//no error 
    System.out.println("res1:"+res1[0]); 

    res = res2;//only once 
    //res = res2;//error already initialised 
    res2[0]=30; 

    System.out.println("res:"+res[0]);  

de salida :: res1: 20 res: 30

+1

Publicar un fragmento de código no se está alineando realmente con el espíritu de desbordamiento de pila. Amable respuesta con contenido, contexto y detalles. – Gyan