Quelle est la différence entre public, protected, package-private et private en Java?


3171

En Java, y at - il des règles claires sur quand utiliser chacun des modificateurs d'accès, à savoir la valeur par défaut (privé paquet), public, protectedet private, tout en faisant classet interfaceet sur la succession?


161
privatemasque les autres classes du package. publicexpose à des classes en dehors du package. protectedest une version de publicrestreinte uniquement aux sous-classes.
Museful

87
@Tennenrishin - Non; contrairement à C ++, en Java, protectedla méthode est également accessible à partir de l'ensemble du package. Cette stupidité dans le modèle de visibilité de Java brise l'objectif de protected.
Nicolas Barbulesco

35
@Nicolas Il est accessible à partir de l'ensemble du package, avec ou sans protected. A titre d'accès modificateur , tout ce qui protectedne fait d'exposer à l' extérieur du colis sous - classes.
Museful

15
@tennenrishin - eh bien, c'est ce que Nicolas a dit ... et vous le répétez maintenant. Ce que vous avez dit à l'origine, c'est que protected- et je cite - `` est une version du public limitée uniquement aux sous-classes '', ce qui n'est pas vrai de votre propre aveu, car protégé permet également d'accéder à l'ensemble du package (ergo, il ne restreint pas l' accès aux sous-classes. )
luis.espinal

10
Je suis également d'accord avec Nicolas en ce que le mode d'accès protégé en Java est idiot. Ce qui s'est passé, c'est que Java a confondu les qualificatifs de restriction d'accès horizontaux (réseau) et verticaux. La portée par défaut est une restriction horizontale / réseau avec le réseau étant le package. Le public est une autre restriction horizontale où le réseau est le monde entier. Privé et (C ++) protégé est vertical. Cela aurait été mieux si nous avions un accès transversal, disons, protected-packagepour les rares cas où nous en avions réellement besoin, laissant protectedl'équivalent de la version C ++ de protected.
luis.espinal

Réponses:


5639

Le tutoriel officiel peut vous être utile.

______________________________________________________________
| │ Classe │ Package │ Sous-classe │ Sous-classe │ Monde |
| │ │ │ (même paquet) │ (paquet différent) │ |
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| public │ + │ + │ + │ + │ + | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| protégé │ + │ + │ + │ + │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| aucun modificateur│ + │ + │ + │ │ | 
| ───────────┼───────┼─────────┼──────────┼──────── ──┼──────── |
| privé │ + │ │ │ │ |
| ___________ | _______ | _________ | __________ | __________ | ________ |
 +: accessible en blanc: non accessible

5
Le tableau ci-dessus est incorrect, car même les privatemembres peuvent être vus / utilisés par n'importe quelle classe / méthode statique dans le même fichier source.
Usagi Miyamoto

5
Le membre protégé n'est accessible qu'à partir de la sous-classe du même package mais pas de la sous-classe d'un package différent. Il devrait y avoir une correction dans le tableau ci-dessus
niks

2
Le monde est dans votre projet . Je devrais expliquer davantage. Les bibliothèques font partie de votre projet et si vous créez une bibliothèque, elles exposeront également ces classes et méthodes publiques. Donc, dire juste au sein de votre projet est un peu décalé. "Tout ce qui l'utilise" est une meilleure description.
adprocas

3
Par exemple, si je l'ai MyClasset que je le fais, AnotherClass extends MyClassj'aurai accès à toutes les méthodes et propriétés publiques et protégées de l'intérieur AnotherClass. Si je fais MyClass myClass = new MyClass();dans AnotherClassquelque part - disons que le constructeur - je n'avoir accès aux méthodes publiques si elle est dans un emballage différent. Notez que si je le fais, = new MyClass() { @Override protected void protectedMethod() { //some logic } };il semble que je puisse accéder aux méthodes protégées, mais ce genre de chose comme l'étendre, mais en ligne à la place.
adprocas

3
Malheureusement, cette réponse est une simplification grossière. La réalité est un peu plus compliquée, surtout si l'on considère protected(ce qui est en fait un modificateur d'accès assez difficile à comprendre pleinement - la plupart des gens qui pensent savoir ce que protectedsignifie vraiment pas). De plus, comme Bohème l'a souligné, il ne répond pas à la question - il ne dit rien sur le moment d'utiliser chaque modificateur d'accès. À mon avis, cette réponse n'est pas assez mauvaise pour dévaloriser, mais ferme. Mais plus de 4000 votes positifs? Comment est-ce arrivé?
Dawood ibn Kareem

483

(Attention: je ne suis pas un programmeur Java, je suis un programmeur Perl. Perl n'a pas de protections formelles, c'est peut-être pourquoi je comprends si bien le problème :))

Privé

Comme vous le pensez, seule la classe dans laquelle il est déclaré peut le voir.

Forfait privé

Il ne peut être vu et utilisé que par le package dans lequel il a été déclaré. C'est la valeur par défaut en Java (que certains considèrent comme une erreur).

Protégé

Le package Private + peut être vu par les sous-classes ou les membres du package.

Publique

Tout le monde peut le voir.

Publié

Visible en dehors du code que je contrôle. (Bien que n'étant pas une syntaxe Java, elle est importante pour cette discussion).

C ++ définit un niveau supplémentaire appelé "ami" et moins vous en savez, mieux c'est.

Quand devez-vous utiliser quoi? L'idée est d'encapsuler pour cacher des informations. Autant que possible, vous souhaitez masquer le détail de la façon dont quelque chose est fait à vos utilisateurs. Pourquoi? Parce qu'alors vous pouvez les changer plus tard et ne casser le code de personne. Cela vous permet d'optimiser, de refactoriser, de repenser et de corriger les bogues sans vous soucier que quelqu'un utilise ce code que vous venez de réviser.

Donc, la règle de base est de rendre les choses aussi visibles qu'elles doivent l'être. Commencez avec privé et ajoutez seulement plus de visibilité si nécessaire. Ne rendez public que ce qui est absolument nécessaire à l'utilisateur, chaque détail que vous rendez public restreint votre capacité à repenser le système.

Si vous souhaitez que les utilisateurs soient en mesure de personnaliser les comportements, plutôt que de rendre les internes publics afin qu'ils puissent les remplacer, il est souvent préférable de pousser ces tripes dans un objet et de rendre cette interface publique. De cette façon, ils peuvent simplement brancher un nouvel objet. Par exemple, si vous écriviez un lecteur de CD et que vous vouliez que le bit "aller chercher des informations sur ce CD" soit personnalisable, plutôt que de rendre ces méthodes publiques, vous mettriez toutes ces fonctionnalités dans son propre objet et ne rendriez public que votre getter / setter d'objet . De cette façon, être avare d'exposer vos tripes encourage une bonne composition et une séparation des préoccupations

Personnellement, je reste fidèle à "privé" et "public". De nombreuses langues OO l'ont juste. "Protégé" peut être pratique, mais c'est vraiment une triche. Une fois qu'une interface est plus que privée, elle est hors de votre contrôle et vous devez chercher dans le code des autres pour trouver des utilisations.

C'est là que l'idée de «publié» entre en jeu. Changer une interface (la refactoriser) nécessite que vous trouviez tout le code qui l'utilise et que vous le changiez aussi. Si l'interface est privée, eh bien pas de problème. S'il est protégé, vous devez aller chercher toutes vos sous-classes. Si c'est public, vous devez aller chercher tout le code qui utilise votre code. Parfois, cela est possible, par exemple, si vous travaillez sur un code d'entreprise à usage interne, peu importe si une interface est publique. Vous pouvez récupérer tout le code du référentiel d'entreprise. Mais si une interface est "publiée", s'il y a du code qui l'utilise hors de votre contrôle, alors vous êtes arrosé. Vous devez prendre en charge cette interface ou risquer de casser le code. Même les interfaces protégées peuvent être considérées comme publiées (c'est pourquoi je ne '

De nombreuses langues trouvent la nature hiérarchique de public / protégé / privé trop limitative et non conforme à la réalité. À cette fin, il y a le concept d'une classe de traits , mais c'est un autre spectacle.


26
amis -> "Moins vous en savez, mieux c'est" ---> Cela donne une visibilité sélective, qui est toujours supérieure à la confidentialité des colis. En C ++, il a ses utilisations, car toutes les fonctions ne peuvent pas être des fonctions membres, et les amis valent mieux que la publication. Bien sûr, il y a un risque d'utilisation abusive par les mauvais esprits.
Sebastian Mach

30
Il convient également de noter que «protégé» en C ++ a une signification différente - une méthode protégée est effectivement privée, mais peut toujours être appelée à partir d'une classe héritée. (Par opposition à Java où il peut être appelé par n'importe quelle classe dans le même paquet.)
Rhys van der Waerden

9
@RhysvanderWaerden C # est le même que C ++ dans cet aspect. Je trouve assez étrange que Java ne permette pas de déclarer un membre accessible à la sous-classe mais pas à l'ensemble du package. C'est un peu à l'envers pour moi - un package a une portée plus large qu'une classe enfant!
Konrad Morawski

15
@KonradMorawski IMHO package a une portée plus petite que la sous-classe. Si vous n'avez pas déclaré votre classe finale, les utilisateurs devraient pouvoir la sous-classer - donc java protected fait partie de votre interface publiée. OTOH, les packages sont implicitement développés par une seule organisation: par exemple com.mycompany.mypackage. Si votre code se déclare dans mon package, vous vous déclarez implicitement membre de mon organisation, nous devons donc communiquer. Ainsi, le package publie à un public plus petit / plus facile à atteindre (personnes de mon entreprise) que la sous-classe (personnes qui étendent mon objet) et compte donc comme une visibilité plus faible.
Éponyme

2
friendest bon pour définir des relations spéciales entre les classes. Il permet une encapsulation supérieure dans de nombreux cas lorsqu'il est utilisé correctement. Par exemple, il peut être utilisé par une classe d'usine privilégiée pour injecter des dépendances internes dans un type construit. Il a une mauvaise réputation parce que les personnes qui ne se soucient pas de maintenir correctement un modèle d'objet bien conçu peuvent en abuser pour alléger leur charge de travail.
Dennis

434

Voici une meilleure version du tableau, qui comprend également une colonne pour les modules.

Modificateurs d'accès Java

Explications

  • Un privé membre ( iest) uniquement accessible au sein de la même classe que elle est déclarée.

  • Un membre sans modificateur d'accès ( j) n'est accessible que dans les classes du même package.

  • Un membre protégé ( k) est accessible dans toutes les classes du même package et dans les sous-classes des autres packages.

  • Un membre public ( l) est accessible à toutes les classes (sauf s'il réside dans un module qui n'exporte pas le package dans lequel il est déclaré).


Quel modificateur choisir?

Les modificateurs d'accès sont un outil pour vous aider à empêcher l'encapsulation accidentelle (*) . Demandez-vous si vous souhaitez que le membre soit interne à la classe, au package, à la hiérarchie des classes ou pas du tout interne, et choisissez le niveau d'accès en conséquence.

Exemples:

  • Un champ long internalCounterdoit probablement être privé car il est modifiable et constitue un détail d'implémentation.
  • Une classe qui ne doit être instanciée que dans une classe d'usine (dans le même package) doit avoir un constructeur restreint au package, car il ne devrait pas être possible de l'appeler directement depuis l'extérieur du package.
  • Une void beforeRender()méthode interne appelée juste avant le rendu et utilisée comme hook dans les sous-classes doit être protégée.
  • Une void saveGame(File dst)méthode appelée à partir du code GUI doit être publique.

(*) Qu'est-ce que l'encapsulation exactement?


11
Je dis juste: il y a beaucoup de gens qui ont des problèmes pour distinguer la coloration rouge / verte. Les tableaux utilisant des schémas de coloration rouge / vert (ou jaune / orange / ...) sont rarement "meilleurs" à quoi que ce soit ;-)
GhostCat

1
@ GhostCat, je ne suis pas d'accord. Je pense que aligne rouge / vert de manière intuitive avec « œuvres » / « ne fonctionne pas » pour beaucoup de gens, à savoir qu'il est mieux que beaucoup d' alternatives.
aioobe

8
colourblindawareness.org/colour-blindness/… ... Les 8% d'hommes daltoniens peuvent être divisés approximativement en 1% de deutéranopes, 1% de protanopes, 1% de protanomalous et 5% de deutéranomalous . Et comme je fais partie de ces 50% de ces 5%, rassurez-vous: le rouge / vert craint.
GhostCat

6
@ GhostCat Ok .. c'est une plus grande partie de la population que ce à quoi je m'attendais. J'ai téléchargé l'image dans ce simulateur de daltonisme et testé tous les différents modes. Même en mode monochromie / achromatopsie, la différence de couleur est raisonnable. Pouvez-vous voir la différence ou le simulateur est-il éteint? (Je suis toujours d'avis que le rouge / vert est très intuitif pour les gens qui voient les couleurs.)
aioobe

3
Je peux voir la différence, mais je peux également passer la moitié des tests de daltonisme que nous devons faire en Allemagne pour le permis de conduire ;-) ... mais je pense qu'un tel simulateur est "assez bon".
GhostCat

206
____________________________________________________________________
                | highest precedence <---------> lowest precedence
*———————————————+———————————————+———————————+———————————————+———————
 \ xCanBeSeenBy | this          | any class | this subclass | any
  \__________   | class         | in same   | in another    | class
             \  | nonsubbed     | package   | package       |    
Modifier of x \ |               |           |               |       
————————————————*———————————————+———————————+———————————————+———————
public          |              |          |              |     
————————————————+———————————————+———————————+———————————————+———————
protected       |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
package-private |               |           |               |
(no modifier)   |              |          |              |      
————————————————+———————————————+———————————+———————————————+———————
private         |              |          |              |       
____________________________________________________________________

1
Il vaut la peine de mettre des mots - "Le modificateur protégé rend l'objet disponible dans d'autres packages, alors que le modificateur par défaut / sans restriction restreint l'accès au même package"
vanguard69

2
@ vanguard69, le protectedmodificateur met la chose marquée (classe, méthode ou champ) à la disposition d'une autre classe dans un autre package uniquement si ladite autre classe est une sous-classe de la classe où cette choseprotected marquée est déclarée.
Abdull

"non soumis"? "cette sous-classe dans un autre package"? Huh. Je pensais que je connaissais Java.
sehe

@AlexanderFarber avez-vous optimisé pour une configuration de navigateur particulière? Ceci est mon chrome maintenant et c'est Firefox
sehe

Hmm, revenons à mon changement alors
Alexander Farber

165

Règle facile. Commencez par déclarer tout privé. Et puis progressez vers le public au fur et à mesure que les besoins se font sentir et que le design le justifie.

Lorsque vous exposez des membres, demandez-vous si vous exposez des choix de représentation ou des choix d'abstraction. Le premier est quelque chose que vous voulez éviter car il introduira trop de dépendances sur la représentation réelle plutôt que sur son comportement observable.

En règle générale, j'essaie d'éviter de surcharger les implémentations de méthodes en sous-classant; c'est trop facile de bousiller la logique. Déclarez les méthodes protégées abstraites si vous avez l'intention de les remplacer.

En outre, utilisez l'annotation @Override lors de la substitution pour empêcher les choses de se casser lorsque vous refactorisez.


3
@RuchirBaronia, "world" = tout le code de l'application, où qu'il se trouve.
Andrejs

116

C'est en fait un peu plus compliqué qu'une simple grille. La grille vous indique si un accès est autorisé, mais qu'est-ce qui constitue exactement un accès? De plus, les niveaux d'accès interagissent avec les classes imbriquées et l'héritage de manière complexe.

L'accès "par défaut" (spécifié par l'absence de mot-clé) est également appelé package-private . Exception: dans une interface, aucun modificateur ne signifie accès public; les modificateurs autres que publics sont interdits. Les constantes d'énumération sont toujours publiques.

Sommaire

Un accès à un membre avec ce spécificateur d'accès est-il autorisé?

  • Le membre est private: uniquement si le membre est défini dans la même classe que le code appelant.
  • Le membre est privé du package: uniquement si le code d'appel se trouve dans le package immédiatement joint au membre.
  • Le membre est protected: le même package ou si le membre est défini dans une superclasse de la classe contenant le code appelant.
  • Le membre est public: Oui.

À quoi s'appliquent les spécificateurs d'accès

Les variables locales et les paramètres formels ne peuvent pas accepter de spécificateurs d'accès. Puisqu'ils sont intrinsèquement inaccessibles à l'extérieur selon les règles de cadrage, ils sont effectivement privés.

Pour les classes de l'étendue supérieure, seuls publicet package-private sont autorisés. Ce choix de conception est probablement parce que protectedet privateserait redondant au niveau du paquet (il n'y a pas d' héritage de colis).

Tous les spécificateurs d'accès sont possibles sur les membres de classe (constructeurs, méthodes et fonctions membres statiques, classes imbriquées).

Connexes: Accessibilité de classe Java

Ordre

Les spécificateurs d'accès peuvent être strictement commandés

public> protégé> package-privé> privé

ce qui signifie que publicle plus d'accès, privatele moins. Toute référence possible sur un membre privé est également valable pour un membre package-private; toute référence à un membre package-private est valide sur un membre protégé, etc. (Donner accès aux membres protégés à d'autres classes dans le même package a été considéré comme une erreur.)

Remarques

  • Les méthodes d'une classe sont autorisées à accéder aux membres privés d'autres objets de la même classe. Plus précisément, une méthode de classe C peut accéder aux membres privés de C sur des objets de n'importe quelle sous-classe de C. Java ne prend pas en charge la restriction d'accès par instance, uniquement par classe. (Comparez avec Scala, qui le supporte en utilisant private[this].)
  • Vous devez avoir accès à un constructeur pour construire un objet. Ainsi, si tous les constructeurs sont privés, la classe ne peut être construite que par du code vivant dans la classe (généralement des méthodes d'usine statiques ou des initialiseurs de variables statiques). De même pour les constructeurs de packages privés ou protégés.
    • Avoir uniquement des constructeurs privés signifie également que la classe ne peut pas être sous-classée en externe, car Java nécessite que les constructeurs d'une sous-classe appellent implicitement ou explicitement un constructeur de superclasse. (Il peut cependant contenir une classe imbriquée qui la sous-classe.)

Classes intérieures

Vous devez également prendre en compte les étendues imbriquées , telles que les classes internes. Un exemple de la complexité est que les classes internes ont des membres, qui peuvent eux-mêmes prendre des modificateurs d'accès. Vous pouvez donc avoir une classe interne privée avec un membre public; le membre est-il accessible? (Voir ci-dessous.) La règle générale consiste à examiner la portée et à réfléchir de manière récursive pour voir si vous pouvez accéder à chaque niveau.

Cependant, c'est assez compliqué, et pour plus de détails, consultez la spécification du langage Java . (Oui, il y a eu des bogues de compilation dans le passé.)

Pour avoir un aperçu de la façon dont ces éléments interagissent, considérez cet exemple. Il est possible de "divulguer" des classes internes privées; c'est généralement un avertissement:

class Test {
    public static void main(final String ... args) {
        System.out.println(Example.leakPrivateClass()); // OK
        Example.leakPrivateClass().secretMethod(); // error
    }
}

class Example {
    private static class NestedClass {
        public void secretMethod() {
            System.out.println("Hello");
        }
    }
    public static NestedClass leakPrivateClass() {
        return new NestedClass();
    }
}

Sortie du compilateur:

Test.java:4: secretMethod() in Example.NestedClass is defined in an inaccessible class or interface
        Example.leakPrivateClass().secretMethod(); // error
                                  ^
1 error

Quelques questions connexes:


1
"les modificateurs autres que publics sont interdits" - depuis Java 9, ce n'est plus le cas: les interfaces peuvent aussi avoir des méthodes privées.
MC Emperor

96

En règle générale:

  • private: portée de la classe.
  • default(ou package-private): étendue du package.
  • protected: package scope + child(comme package, mais nous pouvons le sous-classer à partir de différents packages). Le modificateur protégé conserve toujours la relation "parent-enfant".
  • public: partout.

Par conséquent, si nous divisons le droit d'accès en trois droits:

  • (D) irect (invoquer à partir d'une méthode à l'intérieur de la même classe, ou via "cette" syntaxe).
  • (R) eference (invoquer une méthode utilisant une référence à la classe, ou via la syntaxe "dot").
  • (I) héritage (via le sous- classement ).

alors nous avons ce tableau simple:

+—-———————————————+————————————+———————————+
|                 |    Same    | Different |
|                 |   Package  | Packages  |
+—————————————————+————————————+———————————+
| private         |   D        |           |
+—————————————————+————————————+———————————+
| package-private |            |           |
| (no modifier)   |   D R I    |           |
+—————————————————+————————————+———————————+
| protected       |   D R I    |       I   |
+—————————————————+————————————+———————————+
| public          |   D R I    |    R  I   |
+—————————————————+————————————+———————————+

54

En très court

  • public: accessible de partout.
  • protected: accessible par les classes du même package et les sous-classes résidant dans n'importe quel package.
  • par défaut (aucun modificateur spécifié): accessible par les classes du même package.
  • private: accessible uniquement dans la même classe.

48

Le modificateur d'accès le plus mal compris en Java est protected. Nous savons qu'il est similaire au modificateur par défaut avec une exception dans laquelle les sous-classes peuvent le voir. Mais comment? Voici un exemple qui, espérons-le, clarifie la confusion:

  • Supposons que nous avons 2 classes; Fatheret Son, chacun dans son propre package:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
  • Ajoutons une méthode protégée foo()à Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
  • La méthode foo()peut être appelée dans 4 contextes:

    1. À l'intérieur d'une classe qui se trouve dans le même package où foo()est défini ( fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
    2. Dans une sous-classe, sur l'instance actuelle via thisou super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
    3. Sur une référence dont le type est de la même classe:

      package fatherpackage;
      
      public class Father
      {
          public void fatherMethod(Father f)
          {
              f.foo(); // valid even if foo() is private
          }
      }
      
      -------------------------------------------
      
      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Son s)
          {
              s.foo();
          }
      }
    4. Sur une référence dont le type est la classe parente et se trouve à l' intérieur du package où foo()est défini ( fatherpackage) [Cela peut être inclus dans le contexte no. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
  • Les situations suivantes ne sont pas valides.

    1. Sur une référence dont le type est la classe parent et se trouve en dehors du package où foo()est défini ( fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
    2. Une non-sous-classe à l'intérieur d'un package d'une sous-classe (Une sous-classe hérite des membres protégés de son parent et les rend privés aux non-sous-classes):

      package sonpackage;
      
      public class SomeClass
      {
          public void someMethod(Son s) throws Exception
          {
              s.foo(); // compilation error
          }
      }

Object#clone()est un exemple de protectedmembre.
Eng.Fouad

Quelle est la différence entre faire super.foo()et la première situation invalide f.foo()?
cst1992

1
@ cst1992 C'est déroutant mais voir la spécification du langage Java 6.6.2: "Un membre protégé ou un constructeur d'un objet est accessible depuis l'extérieur du package dans lequel il n'est déclaré que par le code responsable de l'implémentation de cet objet". Avec super.foo () la référence "super" est "directement responsable de l'implémentation" mais la référence "f" ne l'est pas. Pourquoi? Parce que vous pouvez être sûr à 100% que "super" est de type Père, mais pas pour "f"; au moment de l'exécution, il pourrait s'agir d'un autre sous-type de Père. Voir docs.oracle.com/javase/specs/jls/se9/html/…
skomisa

1
C'est rafraîchissant de lire une réponse de quelqu'un qui comprend protected. Malheureusement, toutes les autres réponses sur cette page qui définissent protectedse trompent un peu.
Dawood ibn Kareem

30

Privé

  • Méthodes, variables et constructeurs

Les méthodes, variables et constructeurs déclarés privés ne sont accessibles que dans la classe déclarée elle-même.

  • Classe et interface

Le modificateur d'accès privé est le niveau d'accès le plus restrictif. La classe et les interfaces ne peuvent pas être privées.

Remarque

Les variables déclarées privées sont accessibles en dehors de la classe si des méthodes getter publiques sont présentes dans la classe. Les variables, méthodes et constructeurs déclarés protégés dans une superclasse ne sont accessibles que par les sous-classes d'un autre package ou par n'importe quelle classe du package de la classe des membres protégés.


Protégé

  • Classe et interface

Le modificateur d'accès protégé ne peut pas être appliqué à la classe et aux interfaces.

Les méthodes, les champs peuvent être déclarés protégés, mais les méthodes et les champs d'une interface ne peuvent pas être déclarés protégés.

Remarque

L'accès protégé donne à la sous-classe une chance d'utiliser la méthode ou la variable d'assistance, tout en empêchant une classe non apparentée d'essayer de l'utiliser.


Publique

Une classe, une méthode, un constructeur, une interface, etc. déclarée publique est accessible à partir de n'importe quelle autre classe.

Par conséquent, les champs, méthodes et blocs déclarés à l'intérieur d'une classe publique sont accessibles à partir de n'importe quelle classe appartenant à l'univers Java.

  • Différents packages

Cependant, si la classe publique à laquelle nous essayons d'accéder se trouve dans un package différent, la classe publique doit toujours être importée.

En raison de l'héritage de classe, toutes les méthodes et variables publiques d'une classe sont héritées par ses sous-classes.


Mot-clé -No par défaut:

Le modificateur d'accès par défaut signifie que nous ne déclarons pas explicitement un modificateur d'accès pour une classe, un champ, une méthode, etc.

  • Dans les mêmes packages

Une variable ou une méthode déclarée sans aucun modificateur de contrôle d'accès est disponible pour toute autre classe du même package. Les champs d'une interface sont implicitement publics statiques et les méthodes d'une interface sont par défaut publiques.

Remarque

Nous ne pouvons pas remplacer les champs statiques.

Réponses associées

Liens de références

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html http://www.tutorialspoint.com/java/java_access_modifiers.htm


21

La différence se trouve dans les liens déjà fournis, mais celui à utiliser se résume généralement au "Principe de moindre connaissance". N'autorisez que le moins de visibilité nécessaire.


20

Privé : accès limité à la classe uniquement

Par défaut (pas de modificateur) : accès limité à la classe et au package

Protégé : accès limité aux classes, packages et sous-classes (à l'intérieur et à l'extérieur du package)

Public : accessible aux classes, aux packages (tous) et aux sous-classes ... Bref, partout.


17

Les modificateurs d'accès sont là pour restreindre l'accès à plusieurs niveaux.

Public: C'est fondamentalement aussi simple que vous pouvez y accéder à partir de n'importe quelle classe, que ce soit dans le même package ou non.

Pour accéder si vous êtes dans le même package, vous pouvez accéder directement, mais si vous êtes dans un autre package, vous pouvez créer un objet de la classe.

Par défaut: il est accessible dans le même package à partir de n'importe quelle classe de package.

Pour y accéder, vous pouvez créer un objet de la classe. Mais vous ne pouvez pas accéder à cette variable en dehors du package.

Protégé: vous pouvez accéder aux variables du même package ainsi qu'aux sous-classes de tout autre package. Donc, fondamentalement, c'est le comportement par défaut + hérité .

Pour accéder au champ protégé défini dans la classe de base, vous pouvez créer un objet de classe enfant.

Privé: il peut être accessible dans la même classe.

Dans les méthodes non statiques, vous pouvez accéder directement à cause de cette référence (également dans les constructeurs) mais pour accéder aux méthodes statiques, vous devez créer un objet de la classe.


16

Modificateurs d'accès en Java.

Les modificateurs d'accès Java sont utilisés pour fournir un contrôle d'accès en Java.

1. Par défaut:

Accessible aux classes dans le même package uniquement.

Par exemple,

// Saved in file A.java
package pack;

class A{
  void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B{
  public static void main(String args[]){
   A obj = new A(); // Compile Time Error
   obj.msg(); // Compile Time Error
  }
}

Cet accès est plus restreint que public et protégé, mais moins restreint que privé.

2. Public

Accessible depuis n'importe où. (Accès mondial)

Par exemple,

// Saved in file A.java

package pack;
public class A{
  public void msg(){System.out.println("Hello");}
}

// Saved in file B.java

package mypack;
import pack.*;

class B{
  public static void main(String args[]){
    A obj = new A();
    obj.msg();
  }
}

Sortie: Bonjour

3. Privé

Accessible uniquement à l'intérieur de la même classe.

Si vous essayez d'accéder aux membres privés d'une classe dans une autre, une erreur de compilation sera générée. Par exemple,

class A{
  private int data = 40;
  private void msg(){System.out.println("Hello java");}
}

public class Simple{
  public static void main(String args[]){
    A obj = new A();
    System.out.println(obj.data); // Compile Time Error
    obj.msg(); // Compile Time Error
  }
}

4. Protégé

Accessible uniquement aux classes du même package et aux sous-classes

Par exemple,

// Saved in file A.java
package pack;
public class A{
  protected void msg(){System.out.println("Hello");}
}

// Saved in file B.java
package mypack;
import pack.*;

class B extends A{
  public static void main(String args[]){
    B obj = new B();
    obj.msg();
  }
}

Sortie: Bonjour

Entrez la description de l'image ici


14
  • public - accessible de n'importe où dans l'application.

  • par défaut - accessible à partir du package.

  • protégé - accessible à partir du package et des sous-classes d'un autre package. ainsi que

  • privé - accessible uniquement depuis sa classe.


14

Visible sur l'emballage. Le défaut. Aucun modificateur n'est nécessaire.

Visible uniquement en classe ( privé ).

Visible au monde ( public ).

Visible pour le package et toutes les sous-classes ( protégé ).

Les variables et les méthodes peuvent être déclarées sans aucun modificateur appelé. Exemples par défaut:

String name = "john";

public int age(){
    return age;
}

Modificateur d'accès privé - privé:

Les méthodes, variables et constructeurs déclarés privés ne sont accessibles que dans la classe déclarée elle-même. Le modificateur d'accès privé est le niveau d'accès le plus restrictif. La classe et les interfaces ne peuvent pas être privées.

Les variables déclarées privées sont accessibles en dehors de la classe si des méthodes getter publiques sont présentes dans la classe.

L'utilisation du modificateur privé est le principal moyen par lequel un objet s'encapsule et masque les données du monde extérieur.

Exemples:

Public class Details{

    private String name;

    public void setName(String n){
        this.name = n;
    }

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

Modificateur d'accès public - public:

Une classe, une méthode, un constructeur, une interface, etc. déclarée publique est accessible à partir de n'importe quelle autre classe. Par conséquent, les champs, méthodes, blocs déclarés à l'intérieur d'une classe publique sont accessibles à partir de n'importe quelle classe appartenant à l'univers Java.

Cependant, si la classe publique à laquelle nous essayons d'accéder se trouve dans un package différent, la classe publique doit toujours être importée.

En raison de l'héritage de classe, toutes les méthodes et variables publiques d'une classe sont héritées par ses sous-classes.

Exemple:

public void cal(){

}

Modificateur d'accès protégé - protégé:

Les variables, méthodes et constructeurs déclarés protégés dans une superclasse ne sont accessibles que par les sous-classes d'un autre package ou n'importe quelle classe du package de la classe des membres protégés.

Le modificateur d'accès protégé ne peut pas être appliqué à la classe et aux interfaces. Les méthodes, les champs peuvent être déclarés protégés, mais les méthodes et les champs d'une interface ne peuvent pas être déclarés protégés.

L'accès protégé donne à la sous-classe une chance d'utiliser la méthode ou la variable d'assistance, tout en empêchant une classe non apparentée d'essayer de l'utiliser.

class Van{

    protected boolean speed(){

    }
}

class Car{
    boolean speed(){
    }

}

12

Cette page écrit bien sur le modificateur d'accès protégé et par défaut

.... Protégé: Le modificateur d'accès protégé est un peu délicat et vous pouvez dire qu'il s'agit d'un surensemble du modificateur d'accès par défaut. Les membres protégés sont les mêmes que les membres par défaut en ce qui concerne l'accès dans le même package. La différence est que les membres protégés sont également accessibles aux sous-classes de la classe dans laquelle le membre est déclaré qui sont en dehors du package dans lequel la classe parent est présente.

Mais ces membres protégés ne sont «accessibles en dehors du package que par héritage». c'est-à-dire que vous pouvez accéder à un membre protégé d'une classe dans sa sous-classe présente dans un autre package directement comme si le membre était présent dans la sous-classe elle-même. Mais ce membre protégé ne sera pas accessible dans la sous-classe en dehors du package en utilisant la référence de la classe parent. ....


Juste pour ajouter ceci "Une fois que l'enfant a accès au membre protégé de la classe parent, il devient privé (ou plutôt je dirais un membre privé spécial qui peut être hérité par les sous-classes de la sous-classe) membre de la sous-classe."
Anand

9

La réponse de David donne la signification de chaque modificateur d'accès. Quant à savoir quand les utiliser, je suggère de rendre publiques toutes les classes et les méthodes de chaque classe qui sont destinées à un usage externe (son API), et tout le reste privé.

Au fil du temps, vous découvrirez quand rendre certaines classes privées au package et quand déclarer certaines méthodes protégées pour une utilisation dans des sous-classes.


6

Remarque: Ceci est juste un supplément pour la réponse acceptée.

Ceci est lié aux modificateurs d'accès Java .

Depuis les modificateurs d'accès Java :

Un modificateur d'accès Java spécifie quelles classes peuvent accéder à une classe donnée et à ses champs, constructeurs et méthodes. Les modificateurs d'accès peuvent être spécifiés séparément pour une classe, ses constructeurs, champs et méthodes. Les modificateurs d'accès Java sont également parfois appelés spécificateurs d'accès Java dans le discours quotidien, mais le nom correct est Modificateurs d'accès Java. Les classes, champs, constructeurs et méthodes peuvent avoir l'un des quatre modificateurs d'accès Java différents:

  • Élément de liste
  • privé
  • par défaut (package)
  • protégé
  • Publique

Du contrôle de l'accès aux membres d'une classe didacticiels :

Les modificateurs de niveau d'accès déterminent si d'autres classes peuvent utiliser un champ particulier ou appeler une méthode particulière. Il existe deux niveaux de contrôle d'accès:

  • Au niveau supérieur: public ou package-private (pas de modificateur explicite).
  • Au niveau des membres: public, privé, protégé ou package-private (pas de modificateur explicite).

Une classe peut être déclarée avec le modificateur public, auquel cas cette classe est visible par toutes les classes partout. Si une classe n'a pas de modificateur (la valeur par défaut, également connue sous le nom de package-private), elle n'est visible que dans son propre package

Le tableau suivant montre l'accès aux membres autorisé par chaque modificateur.

╔═════════════╦═══════╦═════════╦══════════╦═══════╗
 Modifier     Class  Package  Subclass  World 
╠═════════════╬═══════╬═════════╬══════════╬═══════╣
 public       Y      Y        Y         Y     
 protected    Y      Y        Y         N     
 no modifier  Y      Y        N         N     
 private      Y      N        N         N     
╚═════════════╩═══════╩═════════╩══════════╩═══════╝

La première colonne de données indique si la classe elle-même a accès au membre défini par le niveau d'accès. Comme vous pouvez le voir, une classe a toujours accès à ses propres membres. La deuxième colonne indique si les classes du même package que la classe (quelle que soit leur filiation) ont accès au membre. La troisième colonne indique si les sous-classes de la classe déclarées en dehors de ce package ont accès au membre. La quatrième colonne indique si toutes les classes ont accès au membre.

Les niveaux d'accès vous affectent de deux manières. Premièrement, lorsque vous utilisez des classes provenant d'une autre source, telles que les classes de la plate-forme Java, les niveaux d'accès déterminent les membres de ces classes que vos propres classes peuvent utiliser. Deuxièmement, lorsque vous écrivez une classe, vous devez décider du niveau d'accès que chaque variable membre et chaque méthode de votre classe doivent avoir.


1
quel est exactement le supplément, et pourquoi n'est-ce pas une modification du message existant?
sehe

le supplément est Access Modifiers. Pourquoi pas un montage? Garder la réponse acceptée inchangée pour des raisons historiques et donner ma réponse.
ישו אוהב אותך

5

Public Protected Default et private sont des modificateurs d'accès.

Ils sont destinés à l'encapsulation, ou à cacher et à afficher le contenu de la classe.

  1. La classe peut être publique ou par défaut
  2. Les membres de la classe peuvent être publics, protégés, par défaut ou privés.

Private n'est pas accessible en dehors de la classe Default n'est accessible que dans le package. Protégé dans le package ainsi que toute classe qui l'étend. Le public est ouvert à tous.

Normalement, les variables membres sont définies comme privées, mais les méthodes membres sont publiques.


Defaultn'est pas un modificateur d'accès, et deux des autres sont mal orthographiés.
Marquis de Lorne

5

Souvent, j'ai réalisé que se souvenir des concepts de base de n'importe quelle langue peut être rendu possible en créant des analogies du monde réel. Voici mon analogie pour comprendre les modificateurs d'accès en Java:

Supposons que vous êtes étudiant dans une université et que vous avez un ami qui vient vous rendre visite ce week-end. Supposons qu'il existe une grande statue du fondateur de l'université au milieu du campus.

  • Lorsque vous l'amenez sur le campus, la première chose que vous et votre ami voyez est cette statue. Cela signifie que quiconque se promène sur le campus peut regarder la statue sans la permission de l'université. Cela rend la statue PUBLIQUE .

  • Ensuite, vous voulez emmener votre ami dans votre dortoir, mais pour cela, vous devez l'enregistrer en tant que visiteur. Cela signifie qu'il obtient un laissez-passer (qui est le même que le vôtre) pour entrer dans divers bâtiments du campus. Cela rendrait sa carte d'accès PROTÉGÉE .

  • Votre ami veut se connecter au WiFi du campus mais n'a pas les informations d'identification pour le faire. Le seul moyen pour lui de se connecter est de partager votre identifiant avec lui. (N'oubliez pas que chaque étudiant qui fréquente l'université possède également ces identifiants de connexion). Cela rendrait vos informations de connexion comme AUCUN MODIFICATEUR .

  • Enfin, votre ami veut lire votre rapport d'avancement pour le semestre qui est affiché sur le site Web. Cependant, chaque étudiant a son propre identifiant pour accéder à cette section du site Web du campus. Cela rendrait ces informations d'identification privées .

J'espère que cela t'aides!


4

Lorsque vous pensez à des modificateurs d'accès, pensez-y simplement de cette façon (s'applique à la fois aux variables et aux méthodes ):

public-> accessible de partout
private-> accessible uniquement dans la même classe où il est déclaré

Maintenant, la confusion survient en ce qui concerne defaultetprotected

default-> Aucun mot-clé modificateur d'accès n'est présent. Cela signifie qu'il est disponible strictement dans le package de la classe. Nulle part en dehors de ce package, il est accessible.

protected-> Légèrement moins strict defaultet en dehors des mêmes classes de package, il est accessible par des sous-classes en dehors du package, il est déclaré.


4

L'accès Java modifie ce que vous pouvez utiliser

entrez la description de l'image ici

Modificateur d'accès peut être applicable class, field[ A propos] , method. Essayez d'accéder à cette sous-classe ou de la remplacer.

  • Accès à fieldou methodvia un class.
  • Héritage. Le classmodificateur d'accès successeur (sous-classe) peut être n'importe lequel. Le methodmodificateur d'accès successeur (prioritaire) doit être le même ou le développer

La classe de niveau supérieur (portée de premier niveau) peut être publicet default. Nested class[À propos] peut avoir n'importe lequel d'entre eux

package n'est pas applicable à la hiérarchie des packages

Modificateurs d'accès rapide


2

Tout est question d' encapsulation (ou, comme l'a déclaré Joe Phillips, le moins de connaissances ).

Commencez avec le plus restrictif (privé) et voyez si vous avez besoin de modificateurs moins restrictifs plus tard.

Nous utilisons tous des modificateurs de méthode et de membre comme privé, public, ... mais une chose trop peu de développeurs font est d'utiliser des packages pour organiser code de manière logique.

Par exemple: vous pouvez placer des méthodes de sécurité sensibles dans un package de «sécurité». Ensuite, mettez une classe publique qui accède à une partie du code lié à la sécurité dans ce package, mais gardez les autres packages de classes de sécurité privés . Ainsi, les autres développeurs ne pourront utiliser la classe accessible au public que depuis l'extérieur de ce package (à moins qu'ils ne modifient le modificateur). Ce n'est pas une fonction de sécurité, mais guidera l' utilisation.

Outside world -> Package (SecurityEntryClass ---> Package private classes)

Une autre chose est que les classes qui dépendent beaucoup les unes des autres peuvent se retrouver dans le même package et pourraient éventuellement être refactorisées ou fusionnées si la dépendance est trop forte.

Si au contraire vous définissez tout comme public, il ne sera pas clair ce qui doit ou ne doit pas être consulté, ce qui peut conduire à écrire beaucoup de javadoc (qui n'applique rien via le compilateur ...).


2

analogie-parfaite-privée-protégée-publique-pour-les-types-de-données-variables

Le diagramme suivant explique comment les membres de données de la classe de base sont hérités lorsque le mode d'accès aux classes dérivées est privé .

entrez la description de l'image ici

Remarque: La déclaration de membres de données avec un spécificateur d'accès privé est appelée masquage de données.

Source: Spécificateurs d'accès - Privé, public et protégé


1
La question concernait Java, pas C ++.
Benoit

1
@Benoit Mais ce que j'ai posté, les images en spécial, ne sont pas les mêmes pour les deux: java et c ++? Ces règles ne s'appliquent pas trop pour java? merci
leonidaa

2
En C ++, il n'y a que 3 modificateurs, alors qu'il y en a 4 en java.
Benoit

1
l'analogie est bonne, mais le spécificateur d'accès par défaut est manquant,
mss

1
OP a posé la question "Quelle est la différence entre public, protected, package-private et private en Java?"
JL_SO

2

Mes deux centimes :)

privé:

classe -> une classe de niveau supérieur ne peut pas être privée. les classes internes peuvent être privées et accessibles à partir de la même classe.

variable d'instance -> accessible uniquement dans la classe. Impossible d'accéder en dehors de la classe.

package-privé:

classe -> une classe de niveau supérieur peut être privée de package. Il ne peut être accessible qu'à partir du même package. Pas du sous-paquet, pas du paquet extérieur.

variable d'instance -> accessible à partir du même package. Pas du sous-paquet, pas du paquet extérieur.

protégé:

classe -> une classe de niveau supérieur ne peut pas être protégée.

variable d'instance -> accessible uniquement dans le même package ou sous-package. Accès uniquement en dehors du package lors de l'extension de la classe.

Publique:

classe -> accessible depuis le package / sous-package / un autre package

variable d'instance -> accessible depuis le package / sous-package / un autre package

Voici la réponse détaillée

https://github.com/junto06/java-4-beginners/blob/master/basics/access-modifier.md


1
  • Publique

    Si un membre de la classe est déclaré avec public, il est accessible depuis n'importe où

  • protégé

    Si un membre de classe est déclaré avec un mot clé protégé, il est accessible à partir des mêmes membres de classe, des membres de classe externes dans le même package et des membres de classe hérités. Si un membre de classe est protégé, il ne peut PAS être accédé à partir de la classe de package externe à moins que la classe packagée externe soit héritée, c'est-à-dire qu'elle étend l'autre superclasse de package. Mais un membre de classe protégé est toujours disponible pour les mêmes classes de package, peu importe que la même classe de package soit héritée ou NON

  • défaut

    En Java, la valeur par défaut n'est PAS un mot-clé de modificateur d'accès. Si un membre de la classe est déclaré sans mot-clé modificateur d'accès, dans ce cas, il est considéré comme membre par défaut. Le membre de classe par défaut est toujours disponible pour les mêmes membres de classe de package. Mais un membre de classe de package externe ne peut PAS accéder aux membres de classe par défaut même si les classes externes sont des sous-classes contrairement aux membres protégés

  • privé

    Si un membre de classe est déclaré avec un mot-clé protégé, dans ce cas, il est disponible UNIQUEMENT pour les mêmes membres de classe


-1

Spécificateurs d'accès en Java: il existe 4 spécificateurs d'accès en java, à savoir privé, package privé (par défaut), protégé et public dans l'ordre d'accès croissant.

Privé : lorsque vous développez une classe et que vous souhaitez que les membres de cette classe ne soient pas exposés en dehors de cette classe, vous devez la déclarer privée. les membres privés ne sont accessibles que dans la classe où ils sont définis, c'est-à-dire dans la classe englobante. les membres privés sont accessibles sur «cette» référence ainsi que sur d'autres instances de classe entourant ces membres, mais uniquement dans la définition de cette classe.

Package-private (par défaut) : ce spécificateur d'accès fournira l'accès spécifié par le spécificateur d'accès privé en plus de l'accès décrit ci-dessous.

Lorsque vous développez un package et donc une classe (disons Class1), vous pouvez utiliser le spécificateur d'accès par défaut (il n'est pas nécessaire de le mentionner explicitement) pour exposer le membre de la classe à d'autres classes de votre (même) package. Dans ces autres classes (dans le même package), vous pouvez accéder à ces membres par défaut sur l'instance de Class1. Vous pouvez également accéder à ces membres par défaut dans les sous-classes de Class1, par exemple Class2 (sur cette référence ou sur l'instance de Class1 ou sur l'instance de Class2).

Fondamentalement, au sein d'un même package, vous pouvez accéder aux membres par défaut sur l'instance de classe directement ou sur «cette» référence dans les sous-classes.

protected : ce spécificateur d'accès fournira l'accès spécifié par le spécificateur d'accès package-private en plus de l'accès décrit ci-dessous.

Lorsque vous développez un package et donc une classe (par exemple Class1), vous devez utiliser un spécificateur d'accès protégé pour le membre de données dans Class1 si vous ne souhaitez pas que ce membre soit accessible en dehors de votre package (par exemple dans le package du consommateur de votre package, c'est-à-dire le client qui utilise vos API) en général, mais vous voulez faire une exception et autoriser l'accès à ce membre uniquement si le client écrit la classe, par exemple Class2 qui étend Class1. Ainsi, en général, les membres protégés seront accessibles sur «cette» référence dans les classes dérivées, c'est-à-dire Class2 et également sur les instances explicites de Class2.

Notez s'il vous plaît:

  1. Vous ne pourrez pas accéder au membre protégé hérité de Class1 dans Class2, si vous essayez d'y accéder sur une instance explicite de Class1, bien qu'il y soit hérité.
  2. Lorsque vous écrivez une autre classe Class3 dans un package identique / différent qui étend Class2, le membre protégé de Class1 sera accessible sur cette référence et également sur l'instance explicite de Class3. Cela sera vrai pour toute hiérarchie étendue, c'est-à-dire que le membre protégé sera toujours accessible sur cette référence ou instance de classe étendue. Notez que dans Class3, si vous créez une instance de Class2, vous ne pourrez pas accéder au membre protégé de Class1 bien qu'il soit hérité.

Donc, en fin de compte, les membres protégés sont accessibles dans d'autres packages, uniquement si une classe de cet autre package, étend la classe entourant ce membre protégé et le membre protégé est accessible sur «cette» référence ou des instances explicites de classe étendue, dans la définition de étendu classe.

public : ce spécificateur d'accès fournira l'accès spécifié par le spécificateur d'accès protégé en plus de l'accès décrit ci-dessous.

Lorsque vous développez un package et donc une classe (disons Class1), alors vous devez utiliser le spécificateur d'accès public pour le membre de données dans Class1 si vous voulez que ce membre soit accessible dans d'autres packages sur une instance de Class1 créée dans une classe d'autres paquet. Fondamentalement, ce spécificateur d'accès doit être utilisé lorsque vous avez l'intention d'exposer votre membre de données au monde sans aucune condition.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.