web-dev-qa-db-fra.com

Avons-nous un champ en lecture seule dans Java (qui est paramétrable dans le cadre de la classe elle-même)?

Comment pouvons-nous avoir une variable qui est inscriptible dans la classe mais seulement "lisible" en dehors d'elle?

Par exemple, au lieu d'avoir à le faire:

Class C {
  private int width, height;

  int GetWidth(){
    return width;
  }

  int GetHeight(){
    return height;
  }

  // etc..

Je voudrais faire quelque chose comme ça:

Class C {
  public_readonly int width, height;

  // etc...

Quelle est la meilleure solution?

35
Pacerier

Il n'y a aucun moyen de le faire en Java.

Vos deux options (celle que vous avez mentionnée) utilisent des getters publics et rendent le champ privé, ou une documentation complète dans la classe.

Les frais généraux sur les méthodes getter sont extrêmement faibles (voire inexistants). Si vous le faites un grand nombre de fois, vous souhaiterez peut-être mettre en cache la valeur récupérée au lieu d'appeler la méthode get.

ÉDITER:

Une façon de le faire, bien qu'il ait encore plus de surcharge que le getter, consiste à définir une classe interne publique (appelons-la innerC) avec un constructeur qui n'est disponible que pour votre classe C, et rendez vos champs publics. De cette façon, vous ne pouvez pas créer d'instances innerC en dehors de votre classe, il est donc impossible de modifier vos champs de l'extérieur, mais vous pouvez les modifier de l'intérieur. Vous pouvez cependant les lire de l'extérieur.

17
Luchian Grigore

Créez une classe avec public final des champs. Fournissez le constructeur où ces champs seraient initialisés. De cette façon, votre classe sera immuable, mais vous n'aurez pas de surcharge pour accéder aux valeurs de l'extérieur. Par exemple:

public class ShortCalendar
{
    public final int year, month, day;

    public ShortCalendar(Calendar calendar)
    {
        if (null == calendar)
            throw new IllegalArgumentException();

        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH);
        day = calendar.get(Calendar.DATE);
    }
}
41
Aleks N.

d'après ce que je sais, le compilateur n'optimise pas ce type de code

Le compilateur Hotspot JIT le fait très certainement .

Je me demandais quelle était la meilleure solution?

Arrêtez d'optimiser prématurément. Si vous utilisez ce code dans une routine de peinture, je peux garantir que la peinture réelle prendra au moins cent fois plus de temps que d'appeler une méthode triviale, même si elle n'est pas intégrée.

6
Michael Borgwardt

il n'y a aucun moyen de rendre un champ "en lecture seule" de l'extérieur. le seul - et le bon - moyen est de rendre les champs privés et de ne fournir que des getters, pas de setters.

3
Thomas Uhrig

En fait, le compilateur HotSpot inclurait très probablement des appels en ligne à vos getters, donc aucune surcharge ne sera impliquée (en plus, la surcharge pour appeler ces méthodes serait difficilement mesurable).

MODIFIER

Si vous avez vraiment besoin de chaque cycle de processeur, utilisez C ou C++ (ou écrivez-y des pièces critiques pour les performances et appelez-le via JNA, bien qu'il soit peu probable qu'il vaudra le temps passé).

1
helpermethod

Votre solution est: champs privés, setters privés, getters protégés ou publics (note: protected permet l'accès à partir du même package ainsi que des sous-classes)

0
U Mad