Idioma

IFreezable Interface

Definição

Fornece um mecanismo flexível para controlar o acesso, sem exigir que uma classe seja imutável.

[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
Implementações

Comentários

Fornece um mecanismo flexível para controlar o acesso, sem exigir que uma classe seja imutável. Uma vez congelado, um objeto nunca pode ser descongelado, portanto, ele é thread-safe a partir desse ponto em diante. Depois que o objeto tiver sido congelado, ele deve garantir que nenhuma alteração possa ser feita a ele. Qualquer tentativa de alterá-la deve gerar uma exceção UnsupportedOperationException. Isso significa que, quando o objeto retorna objetos internos ou se alguém tiver referências a esses objetos internos, esses objetos internos devem ser imutáveis ou também devem gerar exceções se qualquer tentativa de modificá-los for feita. É claro que o objeto pode retornar clones de objetos internos, pois eles são seguros. <h2 Plano de>fundo</h2>

Geralmente, há momentos em que você precisa que os objetos sejam objetos 'seguros', para que eles não possam ser modificados. Exemplos são quando os objetos precisam ser thread-safe ou escrever código robusto ou em caches. Se você estiver criando apenas seus próprios objetos, você pode garantir isso, é claro , mas somente se você não cometer um erro. Se você tiver objetos entregues a você ou estiver criando objetos usando outros entregues a você, será uma história diferente. Tudo se resume a se você quer tomar a abordagem Blanche Dubois (> depender da bondade de estranhos>) ou a abordagem de Andy Grove (> Apenas o Paranoid Survive").

Por exemplo, suponha que tenhamos uma classe simples:

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;
                 }
            }

Como a classe não tem nenhum setters, alguém pode pensar que é imutável. Você sabe onde isso está levando, é claro; essa classe não é segura de várias maneiras. O exemplo a seguir ilustra isso.

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
             }

Há algumas técnicas diferentes para ter classes seguras.

<objetos ol><li>Const. No C++, você pode declarar parâmetros const.</li><li>Wrappers imutáveis. Por exemplo, você pode colocar uma coleção em um wrapper imutável.</li li><>Always-Immutable objetos. Java usa essa abordagem, com algumas variações. Exemplos: <ol><li>Simple. Depois que uma Cor é criada (por exemplo, de inteiros R, G e B), ela é imutável.<Classe /li><li>Builder. Há uma classe "construtor" separada. Por exemplo, cadeias de caracteres modificáveis são criadas usando StringBuffer (que não tem a API de cadeia de caracteres completa disponível). Depois de desejar um formulário imutável, crie um com toString().</li><li>Primitives. Elas são sempre seguras, pois são copiadas na entrada/saída dos métodos.</li></ol></li li><>Cloning. Quando você precisa de um objeto para estar seguro, clone-o.</li></ol>

Há vantagens e desvantagens de cada uma delas.

<ol><li>Const fornece um certo nível de proteção, mas como const pode ser e muitas vezes é expulso, ele só protege contra a maioria dos erros inadvertidas. Ele também não oferece proteção de threading, já que qualquer pessoa que tenha um ponteiro para o objeto (não conectado) em outro thread pode estragar você.</li li><>Wrappers imutáveis são mais seguros do que const em que a constness não pode ser afastada. Mas, fora isso, eles têm todos os mesmos problemas: não seguro se alguém mantiver o objeto original ou se qualquer um dos objetos retornados pela classe for mutável.</li li><>Always-Immutable Objetos são seguros, mas o uso pode exigir a criação excessiva de objetos.</li><li>Cloning só será seguro se o objeto realmente tiver um clone 'seguro'; definido como um que garante que nenhuma alteração no clone afete o original. Infelizmente, muitos objetos não têm um clone 'seguro' e sempre a clonagem pode exigir a criação excessiva de objetos.</li></ol><h2>Modelo< Freezable/h2>

O Freezable modelo complementa essas opções, dando a você a capacidade de criar um objeto chamando vários métodos e, quando ele estiver em um estado final, você pode torná-lo imutável. Uma vez imutável, um objeto nunca pode ser modificado e é completamente thread-safe: ou seja, vários threads podem ter referências a ele sem qualquer sincronização. Se alguém precisar de uma versão mutável de um objeto, poderá usar cloneAsThawed()e modificar a cópia. Isso fornece um mecanismo simples e eficaz para classes seguras em circunstâncias em que as alternativas são insuficientes ou desajeitadas. (Se um objeto for compartilhado antes de ser imutável, será responsabilidade de cada thread ativar o uso do mutex (como com outros objetos).)

Aqui está o que precisa ser feito para implementar essa interface, dependendo do tipo do objeto.

<h3><b>Objetos< Imutáveis/b></h3>

Esses são os mais fáceis. Basta usar a interface para refletir isso, adicionando o seguinte:

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; }
              }

Esses podem ser métodos finais porque as subclasses de objetos imutáveis devem ser imutáveis. (Observação: freeze está retornando this para encadeamento.)

<h3><b>Objetos< Mutáveis/b></h3>

Adicione um campo de 'sinalização' protegido:

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

Adicione os seguintes métodos:

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

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

Adicione um cloneAsThawed() método seguindo o padrão normal para clone(), exceto no frozen=false novo clone.

Em seguida, pegue os setters (ou seja, qualquer método que possa alterar o estado interno do objeto) e adicione o seguinte como a primeira instrução:

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

<h4><b>Subclassing</b></h4>

Qualquer subclasse de um Freezable usará apenas o campo de sinalização de sua superclasse. Ele deve substituir freeze() e cloneAsThawed() chamar a superclasse, mas normalmente não substitui isFrozen(). Em seguida, ele deve apenas prestar atenção aos seus próprios getters, setters e campos.

<h4><b>Caches< Internos/b></h4>

Caches internos são casos em que o objeto é logicamente não modificado, mas o estado interno do objeto é alterado. Por exemplo, há funções const C++ que afastam o const na > this" ponteiro para modificar um cache de objeto. Esses casos são tratados com o mutexing do cache interno para garantir a segurança do thread. Por exemplo, suponha que UnicodeSet tenha um marcador interno para o último ponto de código acessado. Nesse caso, o campo não está visível externamente, portanto, a única coisa que você precisa fazer é sincronizar o campo para a segurança do thread.

<h4>Acesso< Interno Não Seguro/h4>

Os campos internos são chamados de seguros se forem frozen ou imutáveis (como cadeia de caracteres ou primitivas). Se você nunca permitiu acesso interno a elas, você está pronto. Por exemplo, converter UnicodeSet para ser Freezable é feito apenas com as etapas acima. Mas lembre-se de que você <>tem</b> acesso permitido a internos não seguros se você tiver qualquer código como o seguinte, em um getter, setter ou construtor:

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

Elas também ilustradas no exemplo de código em <b>Plano de Fundo</b> acima.

Para lidar com internos não seguros, o curso de ação mais simples é fazer o trabalho na freeze() função. Deixe todos os campos internos congelados e defina o sinalizador congelado. Qualquer getter/setter subsequente funcionará corretamente. Este é um exemplo:

<b>Aviso!</b> O booliano 'congelado' DEVE ser volátil e deve ser definido como a última instrução no método.

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

Se o campo for um Collection ou Map, para torná-lo congelado, você terá duas opções. Se você nunca permitiu o acesso à coleção de fora do objeto, basta embrulhá-la para evitar modificações futuras.

zone_to_country = Collections.unmodifiableMap(zone_to_country);

Se você já permitiu o acesso, faça um clone() antes de embrulhá-lo.

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

Se uma coleção (ou qualquer outro contêiner de objetos) puder conter objetos mutáveis, para um clone seguro, você precisará recursar por meio dela para tornar toda a coleção imutável. O código de recursão deve escolher a coleção mais específica disponível, para evitar a necessidade de downcasing posterior.

<blockquote>

<b>Observação: </b>Uma falha irritante no Java é que as coleções genéricas, como Map ouSet, não têm uma clone() operação. Quando você não sabe o tipo da coleção, o curso mais simples é apenas criar uma nova coleção:

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

</blockquote>

Java documentação para android.icu.util.Freezable.

Partes desta página são modificações baseadas no trabalho criado e compartilhado pelo Project Open Source do Open Source e usadas de acordo com os termos descritos na Creative Commons 2.5.

Propriedades

Nome Description
Handle

Obtém o valor JNI do objeto Android subjacente.

(Herdado de IJavaObject)
IsFrozen

Determina se o objeto foi congelado ou não.

JniIdentityHashCode

Retorna o valor da java.lang.System.identityHashCode() instância encapsulada.

(Herdado de IJavaPeerable)
JniManagedPeerState

Estado do par gerenciado.

(Herdado de IJavaPeerable)
JniObjectReferenceControlBlock

Fornece um mecanismo flexível para controlar o acesso, sem exigir que uma classe seja imutável.

(Herdado de IJavaPeerable)
JniPeerMembers

Acesso ao membro e suporte à invocação.

(Herdado de IJavaPeerable)
PeerReference

Retorna uma JniObjectReference das instâncias de objeto Java encapsuladas.

(Herdado de IJavaPeerable)

Métodos

Nome Description
CloneAsThawed()

Fornece a operação de clone.

Disposed()

Chamado quando a instância foi descartada.

(Herdado de IJavaPeerable)
DisposeUnlessReferenced()

Se não houver referências pendentes a essa instância, então chamará Dispose(); caso contrário, não fará nada.

(Herdado de IJavaPeerable)
Finalized()

Chamado quando a instância foi finalizada.

(Herdado de IJavaPeerable)
Freeze()

Congela o objeto.

SetJniIdentityHashCode(Int32)

Defina o valor retornado por JniIdentityHashCode.

(Herdado de IJavaPeerable)
SetJniManagedPeerState(JniManagedPeerStates)

Fornece um mecanismo flexível para controlar o acesso, sem exigir que uma classe seja imutável.

(Herdado de IJavaPeerable)
SetPeerReference(JniObjectReference)

Defina o valor retornado por PeerReference.

(Herdado de IJavaPeerable)
UnregisterFromRuntime()

Cancele o registro dessa instância para que o runtime não a retorne de invocações futuras Java.Interop.JniRuntime+JniValueManager.PeekValue .

(Herdado de IJavaPeerable)

Métodos de Extensão

Nome Description
GetJniTypeName(IJavaPeerable)

Obtém o nome JNI do tipo da instância self.

JavaAs<TResult>(IJavaPeerable)

Tente coagir a digitar selfTResult, verificando se a coerção é válida no lado Java.

JavaCast<TResult>(IJavaObject)

Executa uma conversão de tipo marcada por runtime do Android.

JavaCast<TResult>(IJavaObject)

Fornece um mecanismo flexível para controlar o acesso, sem exigir que uma classe seja imutável.

TryJavaCast<TResult>(IJavaPeerable, TResult)

Tente coagir a digitar selfTResult, verificando se a coerção é válida no lado Java.

Aplica-se a