Lenguaje

IFreezable Interfaz

Definición

Proporciona un mecanismo flexible para controlar el acceso, sin necesidad de que una clase sea inmutable.

[Android.Runtime.Register("android/icu/util/Freezable", "", "Android.Icu.Util.IFreezableInvoker", ApiSince=24)]
[Java.Interop.JavaTypeParameters(new System.String[] { "T" })]
public interface IFreezable : IDisposable, Java.Interop.IJavaPeerable, Java.Lang.ICloneable
[<Android.Runtime.Register("android/icu/util/Freezable", "", "Android.Icu.Util.IFreezableInvoker", ApiSince=24)>]
[<Java.Interop.JavaTypeParameters(new System.String[] { "T" })>]
type IFreezable = interface
    interface ICloneable
    interface IJavaObject
    interface IDisposable
    interface IJavaPeerable
Derivado
Atributos
Implementaciones

Comentarios

Proporciona un mecanismo flexible para controlar el acceso, sin necesidad de que una clase sea inmutable. Una vez inmovilizado, un objeto nunca puede ser desenfrozen, por lo que es seguro para subprocesos desde ese punto en adelante. Una vez que el objeto se ha inmovilizado, debe garantizar que no se pueda realizar ningún cambio en él. Cualquier intento de modificarlo debe generar una excepción UnsupportedOperationException. Esto significa que cuando el objeto devuelve objetos internos, o si alguien tiene referencias a esos objetos internos, que esos objetos internos deben ser inmutables o también deben generar excepciones si se realiza algún intento de modificarlos. Por supuesto, el objeto puede devolver clones de objetos internos, ya que son seguros. <h2>Fondo</h2>

A menudo, hay ocasiones en las que se necesitan objetos para que sean objetos "seguros", de modo que no se puedan modificar. Algunos ejemplos son cuando los objetos deben ser seguros para subprocesos o escribir código sólido o en cachés. Si solo va a crear sus propios objetos, puede garantizar esto, por supuesto, pero solo si no comete un error. Si tiene objetos entregados o está creando objetos con otros que se le entregan, es una historia diferente. Todo se reduce a si quieres tomar el enfoque Blanche Dubois (" depender de la amabilidad de extraños") o el enfoque andy Grove (" Sólo el Paranoide Sobrevive").

Por ejemplo, supongamos que tenemos una clase simple:

public class A {
                 protected Collection b;

                 protected Collection c;

                 public Collection get_b() {
                         return b;
                 }

                 public Collection get_c() {
                         return c;
                 }

                 public A(Collection new_b, Collection new_c) {
                         b = new_b;
                         c = new_c;
                 }
            }

Dado que la clase no tiene ningún establecedor, alguien podría pensar que es inmutable. Sabes dónde está liderando, por supuesto; esta clase no es segura de varias maneras. A continuación se muestra esto.

public test1(SupposedlyImmutableClass x, SafeStorage y) {
               // unsafe getter
               A a = x.getA();
               Collection col = a.get_b();
               col.add(something); // a has now been changed, and x too

               // unsafe constructor
               a = new A(col, col);
               y.store(a);
               col.add(something); // a has now been changed, and y too
             }

Hay algunas técnicas diferentes para tener clases seguras.

<objetos ol><li>Const. En C++, puede declarar parámetros const.</li li><>contenedores inmutables. Por ejemplo, puede colocar una colección en un contenedor inmutable.</li><li>Always-Immutable objetos. Java usa este enfoque, con algunas variaciones. Ejemplos: <ol><li>Simple. Una vez creado un color (por ejemplo, de R, G y B enteros), es inmutable.</li li><>Builder Class. Hay una clase 'builder' independiente. Por ejemplo, las cadenas modificables se crean mediante StringBuffer (que no tiene disponible la API string completa). Una vez que desee un formulario inmutable, cree uno con toString().</li><>li Primitivos. Siempre son seguros, ya que se copian en la entrada y salida de los métodos.</li></ol></li li><>Clonación. Cuando necesite que un objeto sea seguro, lo clone.</li></ol>

Hay ventajas y desventajas de cada uno de ellos.

<ol><li>Const proporciona un cierto nivel de protección, pero dado que const puede ser y a menudo se elimina, solo protege contra la mayoría de los errores accidentales. Tampoco ofrece protección contra subprocesos, ya que cualquier persona que tenga un puntero al objeto (unconst) en otro subproceso puede arruinarlo.<Los contenedores /li li><>inmutables son más seguros que los const en que la constidad no se puede eliminar. Pero aparte de que tienen todos los mismos problemas: no es seguro si otra persona mantiene presionado el objeto original, o si alguno de los objetos devueltos por la clase son mutables.</li li><>Always-Immutable Objetos son seguros, pero el uso puede requerir la creación excesiva de objetos.</li><>Clonación solo es segura si el objeto realmente tiene un clon "seguro" ; definido como uno que garantiza que ningún cambio en el clon afecte al original. Desafortunadamente, muchos objetos no tienen un clon "seguro", y siempre la clonación puede requerir una creación excesiva de objetos.</li></ol><h2>Freezable Model</h2>

El Freezable modelo complementa estas opciones al darle la capacidad de crear un objeto llamando a varios métodos y, a continuación, cuando se encuentra en un estado final, puede hacer que sea inmutable. Una vez inmutable, un objeto nunca se puede modificar y es completamente seguro para subprocesos: es decir, varios subprocesos pueden tener referencias a él sin ninguna sincronización. Si alguien necesita una versión mutable de un objeto, puede usar cloneAsThawed()y modificar la copia. Esto proporciona un mecanismo sencillo y eficaz para clases seguras en circunstancias en las que las alternativas son insuficientes o torpes. (Si un objeto se comparte antes de que sea inmutable, entonces es responsabilidad de cada subproceso silenciar su uso (como con otros objetos).

Esto es lo que hay que hacer para implementar esta interfaz, en función del tipo del objeto.

<h3><b>Objetos inmutables</b></h3>

Estos son los más fáciles. Solo tiene que usar la interfaz para reflejarlo agregando lo siguiente:

public class A implements Freezable&lt;A&gt; {
              ...
              public final boolean isFrozen() {return true;}
              public final A freeze() {return this;}
              public final A cloneAsThawed() { return this; }
              }

Estos pueden ser métodos finales porque las subclases de objetos inmutables deben ser inmutables. (Nota: freeze devuelve this para encadenar).

<h3><b>Objetos mutables</b></h3>

Agregue un campo "marcado" protegido:

protected volatile boolean frozen; // WARNING: must be volatile

Agregue los métodos siguientes:

public final boolean isFrozen() {
                 return frozen;
            };

            public A freeze() {
                 frozen = true;  // WARNING: must be final statement before return
                 return this;
            }

Agregue un cloneAsThawed() método siguiendo el patrón normal para clone(), excepto en frozen=false el nuevo clon.

A continuación, tome los establecedores (es decir, cualquier método que pueda cambiar el estado interno del objeto) y agregue lo siguiente como la primera instrucción:

if (isFrozen()) {
                 throw new UnsupportedOperationException(&quot;Attempt to modify frozen object&quot;);
            }

<h4><b>Subclasing</b></h4>

Cualquier subclase de un Freezable solo usará el campo de marcado de su superclase. Debe invalidar freeze() y cloneAsThawed() llamar a la superclase, pero normalmente no invalida isFrozen(). Después, debe prestar atención a sus propios captadores, establecedores y campos.

<h4><b>Cachés< internas/b></h4>

Las memorias caché internas son casos en los que el objeto no está modificado lógicamente, pero cambia el estado interno del objeto. Por ejemplo, hay funciones de C++ const que convierten el const en el " este" puntero para modificar una caché de objetos. Estos casos se controlan mediante la exclusión mutua de la memoria caché interna para garantizar la seguridad de los subprocesos. Por ejemplo, supongamos que UnicodeSet tenía un marcador interno al último punto de código al que se ha accedido. En este caso, el campo no es visible externamente, por lo que lo único que debe hacer es sincronizar el campo para la seguridad de subprocesos.

<h4>Acceso interno< no seguro/h4>

Los campos internos se denominan seguros si son frozen o inmutables (como String o primitivos). Si nunca ha permitido el acceso interno a estos, ya ha terminado. Por ejemplo, la conversión de UnicodeSet en se Freezable realiza con los pasos anteriores. Pero recuerde que <b>tiene< permitido> el acceso a elementos internos no seguros si tiene código como el siguiente, en un captador, establecedor o constructor:

Collection getStuff() {
                 return stuff;
            } // caller could keep reference &amp; modify

            void setStuff(Collection x) {
                 stuff = x;
            } // caller could keep reference &amp; modify

            MyClass(Collection x) {
                 stuff = x;
            } // caller could keep reference &amp; modify

También se muestran en el ejemplo de código en <b>Fondo</b> anterior.

Para tratar con elementos internos no seguros, el curso de acción más sencillo es realizar el trabajo en la freeze() función. Solo tiene que hacer que todos los campos internos se inmovilizan y establezcan la marca inmovilizada. Cualquier captador o establecedor posterior funcionará correctamente. Este es un ejemplo:

<b>Advertencia!</b> El booleano 'frozen' DEBE ser volátil y debe establecerse como la última instrucción del método .

public A freeze() {
                 if (!frozen) {
                         foo.freeze();
                         frozen = true;
                 }
                 return this;
            }

Si el campo es o CollectionMap, para hacerlo inmovilizado, tiene dos opciones. Si nunca ha permitido el acceso a la colección desde fuera del objeto, solo tiene que encapsularlo para evitar modificaciones futuras.

zone_to_country = Collections.unmodifiableMap(zone_to_country);

Si alguna vez ha permitido el acceso, realice una clone() acción antes de encapsularla.

zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());

Si una colección (o cualquier otro contenedor de objetos) puede contener objetos mutables, para un clon seguro debe recurse a través de él para que toda la colección sea inmutable. El código recursante debe elegir la colección más específica disponible para evitar la necesidad de una reducción posterior.

<blockquote>

<b>Nota: </b>Un error molesto en Java es que las colecciones genéricas, como Map o Set, no tienen una clone() operación. Cuando no conoce el tipo de la colección, el curso más sencillo es simplemente crear una nueva colección:

zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));

</blockquote>

Java documentación para android.icu.util.Freezable.

Las partes de esta página son modificaciones basadas en el trabajo creado y compartido por el Android y se usan según los términos descritos en creative Creative Commons 2.5 Attribution License.

Propiedades

Nombre Description
Handle

Obtiene el valor JNI del objeto Android subyacente.

(Heredado de IJavaObject)
IsFrozen

Determina si el objeto se ha inmovilizado o no.

JniIdentityHashCode

Devuelve el valor de java.lang.System.identityHashCode() para la instancia ajustada.

(Heredado de IJavaPeerable)
JniManagedPeerState

Estado del mismo nivel administrado.

(Heredado de IJavaPeerable)
JniObjectReferenceControlBlock

Proporciona un mecanismo flexible para controlar el acceso, sin necesidad de que una clase sea inmutable.

(Heredado de IJavaPeerable)
JniPeerMembers

Compatibilidad con la invocación y el acceso de miembros.

(Heredado de IJavaPeerable)
PeerReference

Devuelve un JniObjectReference de la instancia de objeto Java ajustada.

(Heredado de IJavaPeerable)

Métodos

Nombre Description
CloneAsThawed()

Proporciona la operación de clonación.

Disposed()

Se llama cuando se ha eliminado la instancia.

(Heredado de IJavaPeerable)
DisposeUnlessReferenced()

Si no hay referencias pendientes a esta instancia, llama a Dispose(); de lo contrario, no hace nada.

(Heredado de IJavaPeerable)
Finalized()

Se llama cuando se ha finalizado la instancia.

(Heredado de IJavaPeerable)
Freeze()

Inmoviliza el objeto.

SetJniIdentityHashCode(Int32)

Establezca el valor devuelto por JniIdentityHashCode.

(Heredado de IJavaPeerable)
SetJniManagedPeerState(JniManagedPeerStates)

Proporciona un mecanismo flexible para controlar el acceso, sin necesidad de que una clase sea inmutable.

(Heredado de IJavaPeerable)
SetPeerReference(JniObjectReference)

Establezca el valor devuelto por PeerReference.

(Heredado de IJavaPeerable)
UnregisterFromRuntime()

Anule el registro de esta instancia para que el entorno de ejecución no lo devuelva de invocaciones futuras Java.Interop.JniRuntime+JniValueManager.PeekValue .

(Heredado de IJavaPeerable)

Métodos de extensión

Nombre Description
GetJniTypeName(IJavaPeerable)

Obtiene el nombre JNI del tipo de la instancia self.

JavaAs<TResult>(IJavaPeerable)

Intente coerción self para escribir TResult, comprobando que la coerción es válida en el lado de Java.

JavaCast<TResult>(IJavaObject)

Realiza una conversión de tipos comprobados en tiempo de ejecución de Android.

JavaCast<TResult>(IJavaObject)

Proporciona un mecanismo flexible para controlar el acceso, sin necesidad de que una clase sea inmutable.

TryJavaCast<TResult>(IJavaPeerable, TResult)

Intente coerción self para escribir TResult, comprobando que la coerción es válida en el lado de Java.

Se aplica a