IFreezable Interface
Definição
Importante
Algumas informações se referem a produtos de pré-lançamento que podem ser substancialmente modificados antes do lançamento. A Microsoft não oferece garantias, expressas ou implícitas, das informações aqui fornecidas.
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<A> {
...
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("Attempt to modify frozen object");
}
<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 & modify
void setStuff(Collection x) {
stuff = x;
} // caller could keep reference & modify
MyClass(Collection x) {
stuff = x;
} // caller could keep reference & 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 |
| 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á |
| Finalized() |
Chamado quando a instância foi finalizada. (Herdado de IJavaPeerable) |
| Freeze() |
Congela o objeto. |
| SetJniIdentityHashCode(Int32) |
Defina o valor retornado por |
| 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 |
| 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 |
| JavaAs<TResult>(IJavaPeerable) |
Tente coagir a digitar |
| 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 |