W3docs

Attributs de classe Java (Champs)

Déclarez des champs d'instance sur une classe Java, définissez leurs valeurs initiales et accédez-y via des objets.

Les attributs d'une classe sont les variables déclarées à l'intérieur — les données que chaque objet porte. La plupart des auteurs les appellent champs (c'est le terme de la spécification du langage Java), et "attribut" est le terme POO plus général ; ils désignent la même chose. Ce chapitre traite de leur déclaration, des valeurs avec lesquelles ils démarrent, et de la façon de les lire et de les écrire depuis l'extérieur de la classe.

Déclarer un champ

Un champ ressemble à une variable locale, mais il se trouve dans le corps de la classe plutôt qu'à l'intérieur d'une méthode :

public class Book {
  String title;
  String author;
  int    pages;
  boolean inPrint;
}

Chaque instance de Book obtient sa propre copie de ces quatre champs. Deux livres ont deux chaînes title séparées, deux entiers pages séparés, et ainsi de suite. Ils vivent aussi longtemps que l'objet vit, c'est-à-dire jusqu'à ce qu'aucune référence ne pointe plus vers lui.

Valeurs par défaut

Si vous n'initialisez pas un champ, Java l'initialise pour vous. Les valeurs par défaut dépendent du type :

TypeValeur par défaut
byte, short, int, long0
float, double0.0
char'�' (le caractère nul, point de code 0 — pas un espace)
booleanfalse
tout type objetnull
Book b = new Book();
System.out.println(b.title);    // null
System.out.println(b.pages);    // 0
System.out.println(b.inPrint);  // false

C'est l'une des principales différences entre les champs et les variables locales à l'intérieur des méthodes — les variables locales n'ont pas de valeur par défaut, et le compilateur refuse de vous laisser en lire une avant de lui avoir assigné une valeur. Les champs commencent toujours avec quelque chose.

Initialiseurs inline

Vous pouvez donner une valeur à un champ là où vous le déclarez :

public class Book {
  String title   = "Untitled";
  int    pages   = 0;
  boolean inPrint = true;
}

L'initialiseur s'exécute une fois par objet, lors de la création de cet objet. Il s'exécute dans l'ordre de déclaration, avant le corps du constructeur. Si un champ nécessite une configuration plus complexe, c'est le rôle du constructeur.

Lire et écrire des champs

Vous utilisez <référence>.<champ> depuis l'extérieur, et simplement <nomDuChamp> (ou this.<nomDuChamp>) depuis l'intérieur de la classe elle-même :

Book b = new Book();
b.title = "Effective Java";    // write
String t = b.title;            // read

À l'intérieur de la classe :

public class Book {
  String title;
  void rename(String t) {
    title = t;             // same as this.title = t;
  }
}

Le chapitre sur le mot-clé this explique quand vous avez besoin du qualificateur explicite this. et quand vous n'en avez pas besoin.

Conventions de nommage

Les noms de champs Java utilisent le lowerCamelCase :

String firstName;       // good
String first_name;      // not Java style
String FirstName;       // looks like a class

Les booléens sont souvent nommés avec les préfixes is ou has (isPublished, hasIndex), ce qui rend les sites d'appel naturellement lisibles : if (book.isPublished). Les constantes — les champs qui ne changent pas — sont écrites en UPPER_SNAKE_CASE et marquées static final, ce qui est couvert dans les chapitres static et final.

Champs d'instance vs champs de classe

Par défaut, les champs appartiennent à chaque instance — chaque objet a sa propre copie. En ajoutant static, le champ appartient à la classe elle-même ; il n'y a qu'une seule copie, partagée entre toutes les instances :

public class Counter {
  int count;            // instance — each Counter has its own
  static int total;     // class    — one shared by all Counters
}

Counter a = new Counter();
Counter b = new Counter();
a.count++;   b.count++;   b.count++;
Counter.total++;

System.out.println(a.count);          // 1
System.out.println(b.count);          // 2
System.out.println(Counter.total);    // 1, accessed through the class

Vous trouverez l'histoire complète dans le chapitre static ; pour l'instant, supposez que chaque champ est un champ d'instance, sauf s'il est explicitement marqué static.

Les champs publics sont généralement une erreur

Java vous permet d'écrire public String title; et de laisser le code extérieur l'atteindre et le modifier directement. En pratique, vous ne le faites presque jamais. Une fois qu'un champ est public, vous avez perdu la capacité de valider les écritures, de changer le type plus tard, ou d'envelopper les lectures avec de la logique — quiconque touche le champ est codé en dur dans sa représentation actuelle.

Le modèle standard consiste à marquer les champs private et à exposer des getters et setters à la place :

public class Book {
  private String title;

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

C'est l'encapsulation. Les chapitres sur l'encapsulation et les getters & setters couvrent le modèle complet. Nous montrons les champs directement dans les premiers exemples pour la clarté, mais le vrai code Java les garde privés.

Les champs contiennent des références, pas des objets

Lorsque le type d'un champ est une classe (et non un primitif), le champ est une référence. Deux objets peuvent partager le même objet sous-jacent via leurs champs :

public class Author { String name; }
public class Book   { Author author; }

Author a = new Author();
a.name = "Joshua Bloch";

Book b1 = new Book();   b1.author = a;
Book b2 = new Book();   b2.author = a;     // same Author object

a.name = "J. Bloch";
System.out.println(b1.author.name);   // J. Bloch
System.out.println(b2.author.name);   // J. Bloch

Les mêmes avertissements du chapitre précédent s'appliquent : c'est parfois ce que vous voulez, et parfois un bug. Si un Book doit avoir son propre Author, vous assigneriez new Author() à chacun.

Un exemple concret

java— editable, runs on the server

Quelle est la suite ?

Les champs sont l'état d'un objet. L'autre moitié — son comportement — se trouve dans les méthodes déclarées sur la classe. Le prochain chapitre sur les méthodes de classe montre comment attacher des méthodes aux instances et comment elles accèdent aux champs que vous venez de définir.

Pratique

Pratique
Un champ d'instance de type int est déclaré mais jamais assigné. Quelle valeur contient-il lorsque vous le lisez via un objet nouvellement créé ?
Un champ d'instance de type int est déclaré mais jamais assigné. Quelle valeur contient-il lorsque vous le lisez via un objet nouvellement créé ?
Was this page helpful?