IFreezable Interfaccia
Definizione
Importante
Alcune informazioni sono relative alla release non definitiva del prodotto, che potrebbe subire modifiche significative prima della release definitiva. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile.
[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
- Derivato
- Attributi
- Implementazioni
Commenti
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile. Una volta bloccato, un oggetto non può mai essere sfrozen, quindi è thread-safe da quel punto in poi. Dopo che l'oggetto è stato bloccato, deve garantire che non sia possibile apportare modifiche. Qualsiasi tentativo di modifica deve generare un'eccezione UnsupportedOperationException. Ciò significa che quando l'oggetto restituisce oggetti interni o se qualcuno dispone di riferimenti a tali oggetti interni, tali oggetti interni devono essere non modificabili o devono generare eccezioni anche se si tenta di modificarli. Naturalmente, l'oggetto può restituire cloni di oggetti interni, poiché sono sicuri. <h2>Background</h2>
Spesso è necessario che gli oggetti siano "sicuri", in modo che non possano essere modificati. Gli esempi sono i casi in cui gli oggetti devono essere thread-safe o scrivere codice affidabile o nelle cache. Se si creano solo oggetti personalizzati, è possibile garantire questo, naturalmente , ma solo se non si commette un errore. Se si hanno oggetti trasmessi o si creano oggetti usando altri utenti, si tratta di una storia diversa. Tutto dipende dal fatto che tu voglia adottare l'approccio Disoscio Bianca Dubois (" dipende dalla gentilezza degli sconosciuti") o l'approccio di Andy Grove (" Solo il Paranoide Survive").
Si supponga, ad esempio, di avere una classe semplice:
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;
}
}
Poiché la classe non ha setter, qualcuno potrebbe pensare che sia immutabile. Sai dove questo è il primo, naturalmente; questa classe non è sicura in diversi modi. Di seguito viene illustrato quanto segue.
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
}
Esistono alcune tecniche diverse per avere classi sicure.
<ol><li>Const oggetti. In C++, è possibile dichiarare i parametri const.<Wrapper non modificabile /li><li>. Ad esempio, è possibile inserire una raccolta in un wrapper non modificabile.<Oggetti /li><Always-Immutable> . Java usa questo approccio, con alcune varianti. Esempi: <ol><li>Simple. Una volta creato un colore (ad esempio da R, G e B interi), non è modificabile.<Classe /li><li>Builder. Esiste una classe 'builder' separata. Ad esempio, le stringhe modificabili vengono create usando StringBuffer (che non ha l'API String completa disponibile). Dopo aver desiderato un modulo non modificabile, crearne uno con toString().</li><li>Primitives. Questi sono sempre sicuri, poiché vengono copiati in input/output dai metodi.<Clonazione di /li></ol></li.>>< Dove è necessario un oggetto per essere sicuro, clonarlo.</li></ol>
Ci sono vantaggi e svantaggi di ognuno di questi.
<ol><li>Const fornisce un certo livello di protezione, ma poiché const può essere e spesso viene allontanato, protegge solo da errori accidentali. Non offre inoltre alcuna protezione di threading, poiché chiunque abbia un puntatore all'oggetto (unconst) in un altro thread può creare confusione.</li><li>Immutable wrapper sono più sicuri di const in quanto la constness non può essere getta via. Tuttavia, a parte ciò, hanno tutti gli stessi problemi: non sono sicuri se qualcun altro mantiene il blocco dell'oggetto originale o se uno degli oggetti restituiti dalla classe è modificabile.</li><li>Always-Immutable Oggetti sono sicuri, ma l'utilizzo può richiedere una creazione eccessiva di oggetti.</li><li>Cloning è sicuro solo se l'oggetto ha effettivamente un clone "sicuro", definito come uno che garantisce che nessuna modifica al clone influisca sull'originale. Sfortunatamente, molti oggetti non hanno un clone "sicuro" e la clonazione può richiedere una creazione eccessiva di oggetti.</li></ol><h2>Freezable Model</h2>
Il Freezable modello integra queste scelte offrendo la possibilità di creare un oggetto chiamando vari metodi, quindi quando si trova in uno stato finale, è possibile renderlo non modificabile. Una volta non modificabile, un oggetto non può mai essere modificato ed è completamente thread-safe, ovvero più thread possono avere riferimenti a esso senza alcuna sincronizzazione. Se un utente ha bisogno di una versione modificabile di un oggetto, può usare cloneAsThawed()e modificare la copia. Ciò fornisce un meccanismo semplice ed efficace per le classi sicure in circostanze in cui le alternative non sono sufficienti o goffe. Se un oggetto viene condiviso prima che non sia modificabile, è responsabilità di ogni thread di mutexrne l'utilizzo (come con altri oggetti).
Ecco cosa deve essere fatto per implementare questa interfaccia, a seconda del tipo dell'oggetto.
<h3><b>Oggetti< non modificabili/b></h3>
Questi sono i più semplici. È sufficiente usare l'interfaccia per riflettere questa funzionalità aggiungendo quanto segue:
public class A implements Freezable<A> {
...
public final boolean isFrozen() {return true;}
public final A freeze() {return this;}
public final A cloneAsThawed() { return this; }
}
Questi possono essere metodi finali perché le sottoclassi di oggetti non modificabili devono essere non modificabili. Nota: freeze viene restituito this per il concatenamento.
<h3><b>Oggetti modificabili</b></h3>
Aggiungere un campo "contrassegno" protetto:
protected volatile boolean frozen; // WARNING: must be volatile
Aggiungere i metodi seguenti:
public final boolean isFrozen() {
return frozen;
};
public A freeze() {
frozen = true; // WARNING: must be final statement before return
return this;
}
Aggiungere un cloneAsThawed() metodo seguendo il modello normale per clone(), ad eccezione del fatto che frozen=false nel nuovo clone.
Prendere quindi i setter (ovvero qualsiasi metodo che può modificare lo stato interno dell'oggetto) e aggiungere quanto segue come prima istruzione:
if (isFrozen()) {
throw new UnsupportedOperationException("Attempt to modify frozen object");
}
<h4><b>Subclassing</b></h4>
Qualsiasi sottoclasse di un Freezable userà solo il campo di contrassegno della superclasse. Deve eseguire l'override di e cloneAsThawed() per chiamare la superclassefreeze(), ma in genere non esegue l'override di isFrozen(). Deve quindi prestare attenzione ai propri getter, setter e campi.
<h4><b>Cache< interne/b></h4>
Le cache interne sono casi in cui l'oggetto è logicamente non modificato, ma lo stato interno dell'oggetto cambia. Ad esempio, ci sono funzioni C++ const che allontanano il const sulla " this" puntatore per modificare una cache di oggetti. Questi casi vengono gestiti tramite il mutex della cache interna per garantire la thread-safety. Si supponga, ad esempio, che UnicodeSet abbia un marcatore interno all'ultimo punto di codice a cui si accede. In questo caso, il campo non è visibile esternamente, quindi l'unica cosa da fare è sincronizzare il campo per thread safety.
<h4>Accesso< interno non sicuro/h4>
I campi interni vengono chiamati sicuri se sono o non modificabili frozen , ad esempio String o primitive. Se non hai mai consentito l'accesso interno a questi elementi, allora hai finito tutto. Ad esempio, la conversione di UnicodeSet in modo da essere Freezable eseguita solo con i passaggi precedenti. Tenere tuttavia presente che b<> ha<> consentito l'accesso a internals non sicuri se si dispone di codice simile al seguente, in un getter, un setter o un costruttore:
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
Queste informazioni sono illustrate anche nell'esempio di codice in <b>Background</b> precedente.
Per gestire gli interni non sicuri, il corso di azione più semplice consiste nell'eseguire il lavoro nella freeze() funzione. Basta fare tutti i tuoi campi interni congelati e impostare la bandiera bloccata. Qualsiasi getter/setter successivo funzionerà correttamente. Ecco un esempio:
<b>Avviso!</b> Il valore booleano 'frozen' DEVE essere volatile e deve essere impostato come ultima istruzione nel metodo .
public A freeze() {
if (!frozen) {
foo.freeze();
frozen = true;
}
return this;
}
Se il campo è o CollectionMap, per renderlo bloccato sono disponibili due opzioni. Se non è mai stato consentito l'accesso alla raccolta dall'esterno dell'oggetto, è sufficiente eseguirne il wrapping per impedire modifiche future.
zone_to_country = Collections.unmodifiableMap(zone_to_country);
Se è stato consentito l'accesso, eseguire un'operazione clone() prima di eseguirne il wrapping.
zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());
Se una raccolta (o qualsiasi altro contenitore di oggetti) può contenere oggetti modificabili, per un clone sicuro è necessario ripeterla per rendere l'intera raccolta non modificabile. Il codice di recursing deve selezionare la raccolta più specifica disponibile, per evitare la necessità di downcasing successivo.
<blockquote>
<b Nota: </b>>Un difetto fastidioso in Java è che le raccolte generiche, ad esempio Map o Set, non hanno unclone()'operazione. Quando non si conosce il tipo di raccolta, il corso più semplice consiste nel creare una nuova raccolta:
zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));
</blockquote>
per android.icu.util.Freezable.
Le parti di questa pagina sono modifiche basate sul lavoro creato e condiviso dalla e usati in base ai termini descritti in Creative License 2.5 Attribution License.
Proprietà
| Nome | Descrizione |
|---|---|
| Handle |
Ottiene il valore JNI dell'oggetto Android sottostante. (Ereditato da IJavaObject) |
| IsFrozen |
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile. |
| JniIdentityHashCode |
Restituisce il valore di |
| JniManagedPeerState |
Stato del peer gestito. (Ereditato da IJavaPeerable) |
| JniObjectReferenceControlBlock |
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile. (Ereditato da IJavaPeerable) |
| JniPeerMembers |
Supporto per l'accesso ai membri e la chiamata. (Ereditato da IJavaPeerable) |
| PeerReference |
Restituisce un JniObjectReference oggetto dell'istanza dell'oggetto di cui è stato eseguito il wrapping Java. (Ereditato da IJavaPeerable) |
Metodi
| Nome | Descrizione |
|---|---|
| CloneAsThawed() |
Fornisce per l'operazione di clonazione. |
| Disposed() |
Chiamato quando l'istanza è stata eliminata. (Ereditato da IJavaPeerable) |
| DisposeUnlessReferenced() |
Se non sono presenti riferimenti in sospeso a questa istanza, chiama |
| Finalized() |
Chiamato quando l'istanza è stata finalizzata. (Ereditato da IJavaPeerable) |
| Freeze() |
Blocca l'oggetto. |
| SetJniIdentityHashCode(Int32) |
Impostare il valore restituito da |
| SetJniManagedPeerState(JniManagedPeerStates) |
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile. (Ereditato da IJavaPeerable) |
| SetPeerReference(JniObjectReference) |
Impostare il valore restituito da |
| UnregisterFromRuntime() |
Annullare la registrazione di questa istanza in modo che il runtime non lo restituisca dalle chiamate future Java.Interop.JniRuntime+JniValueManager.PeekValue . (Ereditato da IJavaPeerable) |
Metodi di estensione
| Nome | Descrizione |
|---|---|
| GetJniTypeName(IJavaPeerable) |
Ottiene il nome JNI del tipo dell'istanza |
| JavaAs<TResult>(IJavaPeerable) |
Provare a digitare |
| JavaCast<TResult>(IJavaObject) |
Esegue una conversione del tipo di tipo controllato dal runtime Android. |
| JavaCast<TResult>(IJavaObject) |
Fornisce un meccanismo flessibile per controllare l'accesso, senza richiedere che una classe non sia modificabile. |
| TryJavaCast<TResult>(IJavaPeerable, TResult) |
Provare a digitare |