2009-09-06 36 views
32

Necesito un campo booleano mutable en Java (devolveré este campo mediante el método get * más adelante y debería ser posible modificar este campo).Campo booleano mutable en Java

Boolean no funciona porque no hay ningún set * métodos en la clase Boolean (yo diría que Boolean es inmutable, solo puede cambiar la referencia, pero no puede cambiar el objeto).

Supongo que puedo usar una matriz booleana de tamaño 1. ¿Pero probablemente haya soluciones más elegantes?

¿Por qué Java no tiene una cosa tan simple?

+5

valores booleanos se probaron normalmente utilizando métodos de 'isXXX' en lugar de 'getXXX' – pjp

+1

@pjp' isXXX' es solo para esos 'boolean' primitivos. Deberíamos apegarnos a 'getXXX' para esos' Boolean's. –

Respuesta

53

Las clases inmutables son más fáciles de trabajar. Nunca cambiarán y no habrá problemas con el código concurrente. (Básicamente, hay menos posibilidades de romperlos.)

Si desea devolver una referencia a su valor booleano, puede usar java.util.concurrent.atomic.AtomicBoolean si está trabajando con varios hilos o el antiguo org.apache.commons.lang.mutable.MutableBoolean.

+2

Escribí "mutable" en mi objeto de comentario java.lang.String y no pude cambiarlo de nuevo. :-) –

+1

este es intersting. probablemente debería realmente usar AtomicBoolean ... gracias – javapowered

+0

hm .. esto es lo que he leído en javadoc: "Un AtomicBoolean se usa en aplicaciones tales como indicadores actualizados atómicamente, y no se puede utilizar como un reemplazo para un booleano". ¿Por qué? – javapowered

4

¿Por qué no utilizar la primitiva booleana?

p. Ej.

private boolean myFlag = false; 

public void setMyFlag(boolean flag) { 
    myFlag = flag; 
} 

nota Su método getter puede devolver un booleano, si es necesario, debido a la magia de autoboxing. Esto permite una fácil intercambiabilidad entre el uso de primitivas y sus equivalentes de objeto (por ejemplo, booleano frente a booleano o int frente a entero).

Para responder a sus respuestas editadas, re. los métodos que tiene disponibles,

public Object getAttribute(String attributeName) 

se pueden implementar devolviendo un booleano autoboxado.

+0

no quiero agregar un método especial para establecer algo ... todo debe implementarse a través de Objeto devuelto por getAttribute. Esto se debe a que no quiero cambiar la interfaz de clase de jerarquía superior. todo lo que necesito es un objeto booleano mutable ... creo que java.util.concurrent.atomic.AtomicBoolean probablemente la opción correcta – javapowered

+0

Aunque entiendo lo que estás haciendo, diría que no estoy seguro este es un buen diseño Esperaría que el objeto que contiene se ocupe de manipular los campos, en lugar de entregarlos al código de un tercero para que cambie. es decir, es responsabilidad del objeto que lo contiene cuidar sus campos y mantener un estado constante, etc. Solo un aviso (puede estar trabajando bajo restricciones que no conozco, sin embargo) –

+0

estoy de acuerdo en la mayoría de los casos no deberíamos usar tales prácticas. incluso "findbugs" informa "Tipo de retorno de matriz" como un "diseño deficiente" porque los objetos pueden ser cambiados por terceros. Pero esta es la cantidad de código ya escrito y solo necesito añadir algunas cosas más :) Además, desde el nombre de mi campo quedará claro que se supone que debe ser cambiado por terceros, así que creo que debería no será un gran problema :) – javapowered

4

¿Qué tal si usamos la primitiva booleana?

private boolean value; 

public void setValue(boolean value) { 
    this.value = value; 
} 

public boolean getValue() { 
    return value; 
} 
+0

esto funcionará pero tienes que escribir dos métodos para cada campo. pero no quiero cambiar la interfaz existente. el único método que tengo es: public object getAttrbiute (String attributeName) – javapowered

+2

Agregar la capacidad de establecer cosas _is_, en términos de sentido común, cambiando la interfaz. Por lo tanto, es mejor cambiar la interfaz escrita para representar y rastrear ese cambio. – soru

+0

@soru +1 Esa es una gran manera de pensar sobre el problema. – dhable

26

Tal vez escribir usted mismo una clase contenedora

class BooleanHolder { 
    public boolean value; 
} 

O hacer una clase de soporte genérico (lo que significa que tendrá que utilizar la clase Boolean en lugar de primitiva boolean):

class Holder<T> { 
    public T value; 
} 

Usted a continuación, devuelve la clase contenedora en lugar del valor en sí, lo que permite modificar el valor dentro del contenedor.

+4

esto funcionará, pero la matriz de tamaño 1 es un poco más simple, imho :) – javapowered

+0

Usted hace una matriz de BooleanHolders si necesita más de 1 – nos

+0

No le permite usarlo como booleano. –

-1

¿Realmente está diciendo que quiere que las personas que llaman puedan modificar el valor booleano del objeto manipulando lo que se devuelve? ¿Para que el objeto y la persona que llama compartirían una referencia a ella?

Sólo por lo que entienden, dada:

 
class OddClass { 
    private Boolean strangeFlag; 
    public Object getAttrbiute(String attributeName) { 
     if (attributeName.equals("strangeflag")) return (Object)strangeFlag; 
     ... 
    } 
} 

Y entonces la persona que llama hace:

 
    Boolean manipulableFlag = (Boolean) myOddClass.getAttrbiute ("strangeflag"); 

Y más tarde, si la persona que llama cambia el valor de manipulableFlag, desea que se produzca el cambio en el Instancia OddClass, como si el llamador hubiera usado un método setAttrbiute.

¿Eso es lo que estás preguntando?

En ese caso, necesitaría una clase de soporte, como lo sugirió Adam.

+0

eso es correcto, tu comprensión es correcta. clase de sostenedor es una gran solución. al menos puedo usar una matriz de un elemento, pero probablemente java.util.concurrent.atomic.AtomicBoolean es la mejor opción – javapowered

19

Si está utilizando Java 5 o superior a continuación, utilizar AtomicBoolean

+6

@monzonj: las clases 'java.util.concurrent' no usan' synchronized', usan la mucho mejor construcciones de bloqueo optimizadas. 'AtomicBoolean' tendrá una sobrecarga de rendimiento totalmente insignificante cuando se usa como contenido de un' boolean'. si puede demostrar lo contrario, muéstrenos. – skaffman

+5

@monzonj: en ningún caso tiene una sobrecarga de rendimiento significativa en absoluto. También hay mucho que ganar con el uso de la herramienta adecuada para el trabajo correcto. Independientemente de lo que piense de algún golpe de micro-rendimiento que no puede medir, esta clase altamente optimizada fue creada por una razón, dudo que pueda hacerlo mejor. –

+2

@monzonj: su afirmación de que * "las asignaciones atómicas solo pueden realizarse a través de la sincronización" * está mal informada en el mejor de los casos, existe el concepto de * sincronización sin bloqueo * y si realmente observa la fuente de 'AtomicBoolean' lo hará ¡vea que no hay uso de la palabra clave 'synchronized' en ninguna parte! Estás difundiendo información errónea con tu comentario desinformado en el mejor de los casos. –

3

Se puede utilizar una matriz booleana

final boolean[] values = { false }; 
values[0] = true; 
0

Si está usando Android, puede utilizar los objetos android.util.Mutable * cuales envolver varios valores primitivos. Por ejemplo, citando la fuente SDK:

public final class MutableBoolean { 
    public boolean value; 

    public MutableBoolean(boolean value) { 
     this.value = value; 
    } 
} 
1

La respuesta más me gustó fue de Adán a escribir su propia clase contenedora ... OK

/* Boolean to be passed as reference parameter */ 
public class Bool { 

    private boolean value; 

    public Bool() { 
     this.value = false; 
    } 

    public boolean is() { 
     return this.value; 
    } 

    public void setTrue() { 
     this.value = true; 
    } 

    public void setFalse() { 
     this.value = false; 
    } 
} 
Cuestiones relacionadas