Exemples de classes immuables


Je connais déjà la définition des classes immuables mais j'ai besoin de quelques exemples.

Author: Kris, 2011-02-25

10 answers

Quelques classes immuables célèbres dans l'API standard:

  • java.lang.Chaîne (déjà mentionné)
  • Les classes wrapper pour les types primitifs: java.lang.Entier, java.lang.Octet, java.lang.Caractère, java.lang.Bref, java.lang.Boolean, java.lang.Long, java.lang.Double, java.lang.Flotteur
  • java.lang.StackTraceElement (utilisé dans la construction de stacktraces d'exception)
  • La plupart des classes enum sont immuables, mais cela dépend en fait du cas concret. (Ne pas implémentez des énumérations mutables, cela vous bousillera quelque part.) Je pense qu'au moins toutes les classes enum de l'API standard sont en fait immuables.

  • Java.mathématique.BigInteger et java.mathématique.BigDecimal (au moins les objets de ces classes elles-mêmes, les sous-classes pourraient introduire la mutabilité, bien que ce ne soit pas une bonne idée)

  • Java. io. File. Notez que cela représente un objet externe à la machine virtuelle (un fichier sur le système local), qui peut ou non exister, et a certaines méthodes modification et interrogation de l'état de cet objet externe. Mais l'objet Fichier lui-même reste immuable. (Toutes les autres classes dans java.io sont mutables.)

  • Java.awt.Font-représentant une police pour dessiner du texte à l'écran (il peut y avoir des sous-classes mutables, mais cela ne serait certainement pas utile)

  • java.awt.BasicStroke - un objet d'aide pour dessiner des lignes sur des contextes graphiques
  • java.awt.Couleur (au moins des objets de cette classe, certaines sous-classes peuvent être mutable ou en fonction de certains facteurs externes (comme les couleurs du système)), et la plupart des autres implémentations de java.awt.La peinture comme
    • java.awt.GradientPaint,
    • java.awt.LinearGradientPaint
    • java.awt.RadialGradientPaint,
    • (je ne suis pas sûr de java.awt.TexturePaint)
  • Java.awt.Cursor-représentant le bitmap pour le curseur de la souris (ici aussi, certaines sous-classes peuvent être mutables ou en fonction de l'extérieur facteurs)

  • Java.util.Locale-représentant une région géographique, politique ou culturelle spécifique .

  • java.util.UUID - un identifiant unique mondial autant que possible
  • Bien que la plupart des collections soient mutables, il existe des méthodes wrapper dans java.util.Classe Collections, qui renvoie une vue non modifiable sur une collection. Si vous leur passez une collection inconnue nulle part, ce sont en fait des collections immuables. De plus, Collections.singletonMap(), .singletonList, .singleton renvoie des collections immuables à un élément, et il existe également des collections vides immuables.

  • Java. net. URL et java. net. URI-représentant une ressource (sur Internet ou ailleurs)

  • java.net.Inet4Address et java.net.Inet6Address, java.net.InetSocketAddress
  • la plupart des sous-classes de java.sécurité.Autorisation (représentant les autorisations nécessaires pour une action ou données à un code), mais pas java.sécurité.PermissionCollection et les sous-classes.
  • , Toutes les classes de java.time, sauf DateTimeException sont immuables. La plupart des classes des sous-paquets de java.time sont également immuables.

On pourrait dire que les types primitifs sont immuables aussi - vous ne pouvez pas changer la valeur de 42, n'est-ce pas?


La classe AccessControlContext est-elle une classe immuable

AccessControlContext n'a aucune méthode de mutation. Et son état consiste en une liste de ProtectionDomains (qui est une classe immuable) et un DomainCombiner. DomainCombiner est une interface, donc en principe l'implémentation pourrait faire quelque chose de différent à chaque appel.

En fait, le comportement du domaine de protection pourrait également dépendre de la politique actuelle en vigueur - il est discutable de savoir s'il faut appeler un tel objet immuable.

Et AccessController?

Il n'y a pas d'objets de type AccessController, car il s'agit d'une classe finale sans constructeur accessible. Toutes les méthodes sont statiques. On pourrait disons que AccessController n'est ni mutable ni immuable, ou les deux.

La même chose est valable pour toutes les autres classes qui ne peuvent pas avoir d'objets( instances), le plus célèbre:

  • java.lang.Vide
  • java.lang.Système (mais cela a un état statique mutable- in, out, err)
  • java.lang.Math (ceci aussi - le générateur de nombres aléatoires)
  • java.lang.refléter.Tableau
  • java.util.Les Collections de
  • java.util.Tableaux
 96
Author: Paŭlo Ebermann, 2018-04-10 13:43:43

Les classes immuables ne peuvent pas être modifiées après la construction. Ainsi, par exemple, un Java String est immuable.

Pour une classe immuable, vous avez à faire final et tous les champs private et final. Par exemple, la classe suivante est immuable:

public final class Person {

     private final String name;
     private final int age;
     private final Collection<String> friends;

     public Person(String name, int age, Collection<String> friends) {
         this.name = name;
         this.age = age;
         this.friends = new ArrayList(friends);
     }

     public String getName() { 
         return this.name;
     }

     public int getAge() {
         return this.age;
     }

     public Collection<String> getFriends() {
         return Collections.unmodifiableCollection(this.friends);
     }
}

J'ai ajouté une méthode dans l'exemple de code montrant comment gérer les collections, un point important.

Si possible vous devriez rendre les classes immuables, car alors vous n'avez pas à vous soucier des choses comme la sécurité du fil.

 22
Author: christophmccann, 2015-06-18 17:27:47

Il est important de garder à l'esprit que déclarer une classe comme finale ne signifie pas qu'elle est "immuable", cela signifie essentiellement que cette classe ne peut pas être étendue (ou spécialisée).

Les classes immuables doivent avoir des champs privés et finaux (sans setters), donc après sa construction, ses valeurs de champ ne peuvent pas être modifiées.

 13
Author: Luciano Costa, 2011-02-26 00:37:57

Pour créer une classe immuable, vous devez suivre les étapes suivantes:

  1. Déclare la classe comme finale afin qu'elle ne puisse pas être étendue.
  2. Rendre tous les champs privés afin que l'accès direct ne soit pas autorisé.
  3. Ne fournit pas de méthodes setter pour les variables
  4. Rendre tous les champs mutables finaux afin que sa valeur puisse être affectée qu'une seule fois.
  5. Initialise tous les champs via un constructeur effectuant une copie profonde.
  6. Effectuer le clonage d'objets dans les méthodes getter pour renvoyer un copie plutôt que de renvoyer la référence d'objet réelle.

Un exemple peut être trouvé ici.

Nous pouvons également utiliser Builder Pattern pour créer facilement des classes immuables, un exemple peut être trouvé ici.

 10
Author: Pankaj, 2014-01-26 21:52:17

Adresse locale, Les classes LocalTime et LocalDateTime (depuis 1.8) sont également immuables. En fait, ce sujet est sur l'examen OCAJSE8 (1Z0-808), et c'est précisément pourquoi j'ai décidé de le traiter comme un simple commentaire.

Tous primitif classes (comme Boolean, Caractère, Octet, Court, Entier, Long, Float, et Double - ) sont immuables.

de l'Argent et Currency API (prévu pour Java9) devrait également être immuable.

Incidemment, les listessoutenues par un tableau (créées par Arrays.asList(myArray)) sontstructurellement -immuables.

En outre, il existe des cas de frontière tels que java.util.Facultatif (présenté sur l'examen OCP, 1Z0-809), qui est immuable si l'élément contenu est lui-même immuable.

 7
Author: Igor Soudakevitch, 2017-09-20 11:35:40

La documentation Sun (Oracle) contient une excellente liste de contrôle sur la façon de créer un objet immuable.

  1. Ne fournissez pas de méthodes "setter" - méthodes qui modifient les champs ou les objets référencés par les champs.
  2. Rendre tous les champs définitifs et privés.
  3. Ne permet pas aux sous-classes de remplacer les méthodes. La façon la plus simple de le faire est de déclarer la classe comme finale. Une approche plus sophistiquée consiste à rendre le constructeur privé et à construire des instances en usine méthode.
  4. Si les champs d'instance incluent des références à des objets mutables, n'autorisez pas la modification de ces objets:
    • Ne fournissez pas de méthodes qui modifient les objets mutables.
    • Ne partagez pas de références aux objets mutables. Ne stockez jamais de références à des objets externes mutables transmis au constructeur; si nécessaire, créez des copies et stockez des références aux copies. De même, créez des copies de vos objets mutables internes si nécessaire pour éviter de renvoyer le originaux dans vos méthodes.

À Partir de: http://download.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

Le site fournit également des exemples de son utilisation dans une simultanéité contexte mais immutabilité est également utile lors de l'écriture de bibliothèques. Il assure que les appelants à la bibliothèque ne peuvent changer que ce que nous leur permettons.

 3
Author: Bernard, 2011-02-26 00:10:47

String est un bon exemple "réel" d'une classe immuable. Et vous pouvez le contraster avec la classe mutable StringBuilder.


La plupart des classes Java utilisées pour la réflexion sont immuables. Et certains des autres sont "presque immuables": par exemple, les classes qui implémentent Accessible ont juste une méthode setAccessible qui change l'état de l'instance Accessible.


Je suis sûr qu'il y en a beaucoup plus dans les bibliothèques de classes standard.

 3
Author: Stephen C, 2011-02-26 00:23:59

La classe immuable est une classe qui une fois créée, son contenu ne peut pas être modifié. Les objets immuables sont les objets dont l'état ne peut pas être modifié une fois construit. Exemple-String & toutes les classes wrapper java.

Les objets mutables sont les objets dont l'état peut être modifié une fois construit.exemple-StringBuffer Une fois que la valeur a changé l'emplacement de mémoire modifié. Voir l'exemple ci-dessous -

 public static void immutableOperation(){
    String str=new String("String is immutable class in Java object value cann't alter once created...");
    System.out.println(str);
    str.replaceAll("String", "StringBuffer");
    System.out.println(str);
    str.concat("Concating value ");
    System.out.println(str + "HashCode Value  " + str.hashCode());
    str=str.concat("Concating value ");
    System.out.println(str + "HashCode Val  " + str.hashCode());

}

public static void mutableOperation(){
    StringBuffer str=new StringBuffer("StringBuffer is mutable class in Java object value can  alter once created...");
    System.out.println(str + "HashCode Val - " + str.hashCode());
    str.replace(0, 12, "String");
    System.out.println(str + "HashCode Val - " + str.hashCode());

}
 2
Author: jaibardhan, 2012-08-04 13:14:54

J'aime utiliser des exemples qui ont une mutable propriété. Cela aide à comprendre comment les classes immuables fonctionnent vraiment.

Classe mutable

class MutableBook {
    private String title;

    public String getTitle(){
        return this.title;
    }

    public void setTitle(String title){
        this.title = title;
    }
}

Et une implémentation immuable utilisant l'instance mutable d'un livre.

public class ImmutableReader {
    private final MutableBook readersBook;
    private final int page;

    public ImmutableReader(MutableBook book) {
        this(book, 0);
    }

    private ImmutableReader(MutableBook book, int page){
        this.page = page;

        // Make copy to ensure this books state won't change.
        MutableBook bookCopy = new MutableBook();
        bookCopy.setTitle(book.getTitle());
        this.readersBook = bookCopy;
    }


    public MutableBook getBook() {
        // Do not return the book, but a new copy. Do not want the readers
        // book to change it's state if developer changes book after this call.
        MutableBook bookCopy = new MutableBook();
        bookCopy.setTitle(this.readersBook.getTitle());
        return bookCopy;
    }

    public int getPage() {
        // primitives are already immutable.
        return page;
    }

    /**
    * Must return reader instance since it's state has changed.
    **/ 
    public ImmutableReader turnPage() {
        return new ImmutableReader(this.readersBook, page + 1);
    }
}

Pour que votre classe soit vraiment immuable, elle doit rencontrer les cirteria suivants:

  • Tous les membres du groupe sont déclarés définitifs.
  • Toutes les variables utilisées dans une classe au niveau de la classe doivent être instanciées lorsque la classe est construit.
  • Aucune variable de classe ne peut avoir une méthode setter.
    • Ceci est implicite à partir de la première déclaration, mais je veux préciser que vous ne pouvez pas changer l'état de la classe.
  • Tous les objets enfants doivent également être immuables, ou leur état n'a jamais changé dans la classe immuable.
    • Si vous avez une classe avec des propriétés mutables, vous devez la verrouiller. Déclarez-le privé et assurez-vous de ne jamais changer son état.

À en savoir un peu plus jetez un oeil à mon article de blog: http://keaplogik.blogspot.com/2015/07/java-immutable-classes-simplified.html

 1
Author: keaplogik, 2015-07-12 01:45:52

Lors de la création d'un objet d'une classe immuable, il faut s'assurer que la référence externe ne sera pas stockée. Toutefois, les valeurs n'est question ici. Dans l'exemple donné ci-dessous, j'ai une classe appelée Fruits à l'intérieur il y a une Liste. J'ai rendu la classe immuable en rendant la liste privée et finale ainsi qu'il n'y a pas de setter fourni.

  1. Si j'instancie un objet de Fruit, le constructeur recevra une liste.Le programme client a une référence de cette liste déjà (côté client) et donc la liste peut être modifiée facilement et donc l'immutabilité de la classe sera perdue.

  2. Pour résoudre ce problème , je crée une nouvelle liste dans le constructeur qui copie toutes les valeurs fournies par le client.

  3. Maintenant, si le client ajoute plus de valeurs dans la liste, la référence externe sera affectée cependant, je ne stocke plus cette référence externe dans ma classe immuable.

  4. Cela peut être vérifié par remplacer un hashcode () dans la classe immuable. Peu importe le nombre de fois que le client modifie la liste, le hashcode de mon objet de classe immuable restera inchangé, car la liste qu'il accepte ne pointe plus vers la liste externe.

Fruit de classe publique {

private final List<String> fruitnames;

public Fruit(List<String> fruitnames) {
    this.fruitnames = new ArrayList<>(fruitnames);
}

public List<String> getFruitnames() {
     return new ArrayList<>(fruitnames);
}

@Override
public int hashCode() {
    return getFruitnames() != null ? getFruitnames().hashCode(): 0;
}

}

//Programme client

Classe publique ImmutableDemo {

public static void main(String args[]){

    List<String> fruitList = new ArrayList<>();
    fruitList.add("Apple");
    fruitList.add("Banana");
    //Immutable Object 1
    Fruit fruit1 = new Fruit(fruitList);
    //fruitHash is-689428840
    int fruitHash = fruit1.hashCode();

    System.out.println("fruitHash is" +fruitHash);
    //This value will not be added anymore as the state has already been defined and
    //now it cant change the state.
    fruitList.add("straberry");
    //fruitHash1 is-689428840
    int fruitHash1 = fruit1.hashCode();


    System.out.println("fruitHash1 is" +fruitHash1);
}

}

 0
Author: Amruta, 2018-08-08 16:20:12