IFreezable Interface
Définition
Important
Certaines informations portent sur la préversion du produit qui est susceptible d’être en grande partie modifiée avant sa publication. Microsoft exclut toute garantie, expresse ou implicite, concernant les informations fournies ici.
Fournit un mécanisme flexible pour contrôler l’accès, sans exiger qu’une classe soit immuable.
[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
- Dérivé
- Attributs
- Implémente
Remarques
Fournit un mécanisme flexible pour contrôler l’accès, sans exiger qu’une classe soit immuable. Une fois figé, un objet ne peut jamais être défrozen. Il est donc thread-safe à partir de ce point. Une fois l’objet figé, il doit garantir qu’aucune modification ne peut y être apportée. Toute tentative de modification doit déclencher une exception UnsupportedOperationException. Cela signifie que lorsque l’objet retourne des objets internes, ou si quelqu’un a des références à ces objets internes, que ces objets internes doivent être immuables ou doivent également déclencher des exceptions si une tentative de modification est effectuée. Bien sûr, l’objet peut retourner des clones d’objets internes, car ceux-ci sont sécurisés. <h2>Background</h2>
Il existe souvent des moments où vous avez besoin d’objets « sécurisés », afin qu’ils ne puissent pas être modifiés. Par exemple, les objets doivent être thread-safe, ou écrire du code robuste ou dans des caches. Si vous créez uniquement vos propres objets, vous pouvez garantir cela, bien sûr, mais seulement si vous ne faites pas d’erreur. Si vous avez des objets remis à vous ou créez des objets à l’aide d’autres personnes qui vous sont transmises, il s’agit d’une histoire différente. Il s’agit de savoir si vous voulez adopter l’approche Blanche Dubois (" dépend de la gentillesse des étrangers") ou l’approche Andy Grove (" Seul le Paranoid Survive").
Par exemple, supposons que nous avons une classe 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;
}
}
Étant donné que la classe n’a pas de setters, quelqu’un peut penser qu’il est immuable. Vous savez où cela mène, bien sûr ; cette classe est dangereuse de plusieurs façons. L’exemple suivant illustre cela.
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
}
Il existe quelques techniques différentes pour avoir des cours sûrs.
<ol><li>Const objets. En C++, vous pouvez déclarer des paramètres const.</li li><>immuable wrappers. Par exemple, vous pouvez placer une collection dans un wrapper immuable.</li li><>Always-Immutable objets. Java utilise cette approche, avec quelques variantes. Exemples : <ol><li>Simple. Une fois qu’une couleur est créée (par exemple, à partir des entiers R, G et B), elle est immuable.</li><>Builder, classe. Il existe une classe « builder » distincte. Par exemple, les chaînes modifiables sont créées à l’aide de StringBuffer (qui n’a pas l’API string complète disponible). Une fois que vous souhaitez un formulaire immuable, vous en créez un avec toString().</li li><>Primitives. Celles-ci sont toujours sécurisées, car elles sont copiées sur les méthodes d’entrée/sortie.</li></ol></li><>Clonage. Là où vous avez besoin d’un objet pour être sûr, vous le clonez.</li></ol>
Il existe des avantages et des inconvénients de chacun d’entre eux.
<ol><li>Const fournit un certain niveau de protection, mais étant donné que const peut être et est souvent jeté, il protège uniquement contre la plupart des erreurs accidentelles. Il n’offre également aucune protection de thread, car toute personne disposant d’un pointeur vers l’objet (nonconst) dans un autre thread peut vous gâcher.</li li><>immuable wrappers sont plus sûrs que const dans le fait que la constness ne peut pas être castée. Mais à part cela, ils ont tous les mêmes problèmes : pas sûr si quelqu’un d’autre conserve la conservation de l’objet d’origine, ou si l’un des objets retournés par la classe est mutable.</li li><>Always-Immutable Objects sont sécurisés, mais l’utilisation peut nécessiter une création excessive d’objets.</li><>Clonage n’est sûr que si l’objet a réellement un clone « sécurisé » ; défini comme un clone qui garantit qu’aucune modification du clone n’affecte l’original. Malheureusement, de nombreux objets n’ont pas de clone « sécurisé », et le clonage peut toujours nécessiter une création excessive d’objets.</li></ol><h2>Freezable Model</h2>
Le Freezable modèle complète ces choix en vous donnant la possibilité de créer un objet en appelant différentes méthodes, puis lorsqu’il est dans un état final, vous pouvez le rendre immuable. Une fois immuable, un objet ne peut jamais être modifié et est complètement thread-safe : autrement dit, plusieurs threads peuvent avoir des références à celui-ci sans aucune synchronisation. Si quelqu’un a besoin d’une version mutable d’un objet, il peut utiliser cloneAsThawed()et modifier la copie. Cela fournit un mécanisme simple et efficace pour les classes sécuritaires dans des circonstances où les alternatives sont insuffisantes ou maladroites. (Si un objet est partagé avant qu’il ne soit immuable, il incombe à chaque thread de muter son utilisation (comme avec d’autres objets).)
Voici ce qui doit être fait pour implémenter cette interface, en fonction du type de l’objet.
<h3><b>Objets< immuables/b></h3>
Ce sont les plus simples. Vous utilisez simplement l’interface pour refléter cela, en ajoutant les éléments suivants :
public class A implements Freezable<A> {
...
public final boolean isFrozen() {return true;}
public final A freeze() {return this;}
public final A cloneAsThawed() { return this; }
}
Il peut s’agir de méthodes finales, car les sous-classes d’objets immuables doivent elles-mêmes être immuables. (Remarque : freeze retourne this pour le chaînage.)
<h3><b>Mutable Objects</b></h3>
Ajoutez un champ protégé « flagging » :
protected volatile boolean frozen; // WARNING: must be volatile
Ajoutez les méthodes suivantes :
public final boolean isFrozen() {
return frozen;
};
public A freeze() {
frozen = true; // WARNING: must be final statement before return
return this;
}
Ajoutez une cloneAsThawed() méthode suivant le modèle normal pour clone(), sauf que frozen=false dans le nouveau clone.
Ensuite, prenez les setters (autrement dit, n’importe quelle méthode qui peut modifier l’état interne de l’objet) et ajoutez ce qui suit comme première instruction :
if (isFrozen()) {
throw new UnsupportedOperationException("Attempt to modify frozen object");
}
<h4><b>Sous-classe</b></h4>
Toute sous-classe d’un Freezable utilisera simplement le champ d’indicateur de sa superclasse. Il doit remplacer freeze() et cloneAsThawed() appeler la superclasse, mais normalement ne remplace isFrozen()pas . Il doit alors simplement prêter attention à ses propres getters, setters et champs.
<h4><b>Caches< internes/b></h4>
Les caches internes sont des cas où l’objet est logiquement non modifié, mais l’état interne de l’objet change. Par exemple, il existe des fonctions const C++ qui cassent le const sur le " this" pointeur pour modifier un cache d’objets. Ces cas sont gérés en mutexant le cache interne pour garantir la sécurité des threads. Par exemple, supposons que UnicodeSet disposait d’un marqueur interne au dernier point de code accessible. Dans ce cas, le champ n’est pas visible en externe. La seule chose à faire est de synchroniser le champ pour la sécurité des threads.
<h4>Accès< interne non sécurisé/h4>
Les champs internes sont appelés sécurisés s’ils sont soit frozen immuables (par exemple, chaîne ou primitives). Si vous n’avez jamais autorisé l’accès interne à ceux-ci, vous êtes tous terminés. Par exemple, la conversion d’UnicodeSet à effectuer Freezable est simplement effectuée avec les étapes ci-dessus. Mais n’oubliez pas que vous <avez b>autorisé<> l’accès à des éléments internes non sécurisés si vous avez du code comme suit, dans un getter, un setter ou un constructeur :
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
Ceux-ci sont également illustrés dans l’exemple de code dans <b>Arrière-plan</b> ci-dessus.
Pour traiter les internes non sécurisés, le cours d’action le plus simple consiste à effectuer le travail dans la freeze() fonction. Faites simplement figer tous vos champs internes et définissez l’indicateur figé. Tout getter/setter ultérieur fonctionne correctement. Voici un exemple :
<b>Avertissement !</b> La valeur booléenne « figée » doit être volatile et doit être définie comme dernière instruction de la méthode.
public A freeze() {
if (!frozen) {
foo.freeze();
frozen = true;
}
return this;
}
Si le champ est un Collection ou Map, pour le faire figé, vous avez deux choix. Si vous n’avez jamais autorisé l’accès à la collection en dehors de votre objet, il vous suffit de l’encapsuler pour empêcher toute modification ultérieure.
zone_to_country = Collections.unmodifiableMap(zone_to_country);
Si vous avez déjà autorisé l’accès, effectuez une clone() opération avant de l’encapsuler.
zone_to_country = Collections.unmodifiableMap(zone_to_country.clone());
Si une collection (ou tout autre conteneur d’objets) elle-même peut contenir des objets mutables, pour un clone sécurisé, vous devez le parcourir pour rendre la collection entière immuable. Le code récursivité doit choisir la collection la plus spécifique disponible, afin d’éviter la nécessité d’effectuer une descente ultérieure.
<blockquote>
<b>Remarque : </b>Un défaut ennuyeux dans Java est que les collections génériques, comme Map ou Set, n'ont pas dclone()'opération. Lorsque vous ne connaissez pas le type de la collection, le cours le plus simple consiste à simplement créer une collection :
zone_to_country = Collections.unmodifiableMap(new HashMap(zone_to_country));
</blockquote>
Java documentation pour android.icu.util.Freezable.
Les parties de cette page sont des modifications basées sur le travail créé et partagé par Android Open Source et utilisées en fonction des termes décrits dans la Creative Commons 2.5 Attribution License.
Propriétés
| Nom | Description |
|---|---|
| Handle |
Obtient la valeur JNI de l’objet Android sous-jacent. (Hérité de IJavaObject) |
| IsFrozen |
Détermine si l’objet a été figé ou non. |
| JniIdentityHashCode |
Retourne la valeur de |
| JniManagedPeerState |
État de l’homologue managé. (Hérité de IJavaPeerable) |
| JniObjectReferenceControlBlock |
Fournit un mécanisme flexible pour contrôler l’accès, sans exiger qu’une classe soit immuable. (Hérité de IJavaPeerable) |
| JniPeerMembers |
Prise en charge de l’accès aux membres et de l’appel. (Hérité de IJavaPeerable) |
| PeerReference |
Retourne une JniObjectReference instance d’objet Java encapsulée. (Hérité de IJavaPeerable) |
Méthodes
| Nom | Description |
|---|---|
| CloneAsThawed() |
Fournit l’opération de clonage. |
| Disposed() |
Appelé lorsque l’instance a été supprimée. (Hérité de IJavaPeerable) |
| DisposeUnlessReferenced() |
S’il n’existe aucune référence en suspens à cette instance, les appels |
| Finalized() |
Appelé lorsque l’instance a été finalisée. (Hérité de IJavaPeerable) |
| Freeze() |
Fige l’objet. |
| SetJniIdentityHashCode(Int32) |
Définissez la valeur retournée par |
| SetJniManagedPeerState(JniManagedPeerStates) |
Fournit un mécanisme flexible pour contrôler l’accès, sans exiger qu’une classe soit immuable. (Hérité de IJavaPeerable) |
| SetPeerReference(JniObjectReference) |
Définissez la valeur retournée par |
| UnregisterFromRuntime() |
Annulez l’inscription de cette instance afin que le runtime ne le retourne pas à partir d’appels futurs Java.Interop.JniRuntime+JniValueManager.PeekValue . (Hérité de IJavaPeerable) |
Méthodes d’extension
| Nom | Description |
|---|---|
| GetJniTypeName(IJavaPeerable) |
Obtient le nom JNI du type de l’instance |
| JavaAs<TResult>(IJavaPeerable) |
Essayez de forcer |
| JavaCast<TResult>(IJavaObject) |
Effectue une conversion de type vérifiée par le runtime Android. |
| JavaCast<TResult>(IJavaObject) |
Fournit un mécanisme flexible pour contrôler l’accès, sans exiger qu’une classe soit immuable. |
| TryJavaCast<TResult>(IJavaPeerable, TResult) |
Essayez de forcer |