2009-10-27 28 views

Respuesta

22

No, una clase final significa que no puede heredar de ella. No tiene nada que ver con la mutabilidad. La siguiente clase es definitiva pero mutable:

public final class FinalMutable { 
    int value; 
    public void setValue(int v) { value=v; } 
    public int getValue() { return value; } 
} 
+2

Para que la clase sea inmutable, tengo que eliminar el setter() método fuera de la clase y también hacer que su variable de instancia (que en este caso es "valor") final. ¿Estoy correcto ...? – Gourav

+1

Sí, debe eliminar el colocador y hacer que el "valor" sea el definitivo. –

+1

Para agregar a eso, Rytmis hace un buen punto a continuación. Si el valor es un objeto mutable, ¿su objeto es realmente inmutable? Lo mejor es hacer que el valor sea privado y cambiar getValue para hacer una copia defensiva. –

30

No, final significa que la clase no se puede extender. No dice nada sobre la mutabilidad. Por ejemplo:

final class MutInt { 
    public int modifyMe; 
} 
9

No hay palabras clave para la inmutabilidad, es más como un patrón de diseño.

EDITAR:
Esto significa, no hay palabra clave, que hace que una clase sea inmutable. Para hacer que una clase sea inmutable, debes proteger las partes internas haciéndolas definitivas o privadas.

Lo confuso es esto: la palabra clave final tiene diferentes significados cuando se usa en una clase y luego cuando se usa en un campo/variable. El primero significa "esta clase no se puede extender". El segundo significa "esta variable (o referencia) no puede ser cambiada".

+3

existe la palabra clave "final" para campos y variables, pero no hace que el objeto sea inmutable, solo la referencia. – Rytmis

+0

@Rytmis: Sí, correcto, pero no hay keyowrd que haga que una clase sea inmutable, como java.lang.String. Editaré la respuesta para aclarar esto. –

+1

Y aún más confuso, el uso de campos 'finales' también se ha sobrecargado con semántica específica en el Modelo de memoria de Java (desde 1.5). – Grundlefleck

5

En relación con las otras respuestas, si nos fijamos en el código para java.lang.String verá que contiene un campo: hash, que es mutable y es, de hecho, cuando se calcula y almacena hashCode() es llamado por primera vez.

Sin embargo, la clase sigue siendo inmutable: no se puede acceder directamente o modificar el campo hash fuera de la clase.

Además, puede observar que un enfoque común dentro del JDK es la implementación de envolturas inmutables que se pueden usar para exponer el estado interno de un objeto sin permitir que se modifique; p.ej.

private final List<String> values; 

public List<? get String> getValues() { 
    return Collections.unmodifiableList(values); 
} 
+0

Y, lo que es crucial para la seguridad del hilo, la asignación diferida del campo hash es una carrera de datos * benigna *. Si no fuera así, dos usuarios de hashCode(), en diferentes subprocesos, podrían ver dos valores diferentes. – Grundlefleck

5

Como se ha dicho por los demás antes de final no hace imuutable clase en Java pesar de que juega un papel en la estrategia de la inmutabilidad. Para obtener la inmutabilidad debe seguir las actuales directivas generales:

  • asegurar la clase no puede ser invalidado - hacer que la clase final o utilice fábricas estáticas y mantener constructores privados
  • crea campos private y final
  • fuerza de las personas que llaman construir un objeto completamente en un solo paso, en lugar de utilizar un constructor sin argumentos combinado con llamadas posteriores a los métodos setXXX (es decir, evitar la convención de Java Beans)
  • no proporciona ningún método que pueda cambiar el estado del objeto t de ninguna manera - no sólo setXXX métodos, pero cualquier método que puede cambiar de estado
  • si la clase tiene ningún campo de objetos mutables, entonces deben ser copiados a la defensiva cuando se pasa entre la clase y su llamador
+0

+ agregar un administrador de seguridad ¡deshabilite cambiar la bandera accesible usando el reflejo! –

+1

Una cosa más: asegúrese de hacer copias defensivas de cualquier argumento mutable en los constructores. Esto está cubierto en Effective Java, 2nd Ed., Item # 15 –

+0

Ahh sí Acabo de buscar el elemento # 15-> 5, pero el punto real se hace en el elemento # 39 para constructores y el elemento # 76 para los métodos 'readObject' –

2

El no se puede acceder al campo privado por los métodos reemplazados de la subclase ... Así que no hay manera de que los métodos de la subclase cambien el campo privado de la superclase ... Entonces, ¿de qué sirve hacer que la clase inmutable sea definitiva?

0

Las palabras clave finales evitan que las otras clases lo hereden. La palabra clave final no la hace inmutable, pero existen condiciones tales como hacer que los miembros de la clase de instancia sean privados y definitivos y usar getters y no usar setters

Cuestiones relacionadas