Frage In Java unterscheiden sich die Pakete privat, öffentlich, geschützt und privat


Gibt es in Java klare Regeln für die Verwendung der einzelnen Zugriffsmodifizierer, nämlich den Standardwert (Paket privat), public, protected und privatewährend der Herstellung class und interface und Umgang mit Vererbung?


2490
2017-10-18 19:53


Ursprung


Antworten:


Das offizielle Tutorial kann dir von Nutzen sein.

            │ Klasse │ Paket │ Unterklasse │ Unterklasse │ Welt
            Same │ │ (gleiches Paket) │ (diff pkg) │
─────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────────────────
öffentlich │ + │ + │ + │ + │ +
─────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────────────────
geschützt │ + │ + │ + │ + │
─────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────────────────
kein Modifikator │ + │ + │ + │ │
─────────────────────────────────────────────────────────────────────────────────────────────────────── ─────────────────────────
privat │ + │ │ │ │

+: zugänglich
leer: nicht erreichbar

4645
2017-10-18 19:57



(Achtung: Ich bin kein Java-Programmierer, ich bin ein Perl-Programmierer. Perl hat keinen formellen Schutz, weshalb ich das Problem vielleicht so gut verstehe :))

Privatgelände

Wie du denkst, nur die Klasse in dem es erklärt wird, kann es sehen.

Paket privat

Kann nur gesehen und verwendet werden von der Paket in dem es erklärt wurde. Dies ist der Standard in Java (was einige als Fehler sehen).

Geschützt

Das Paket Private + kann von Unterklassen oder Paketmitgliedern gesehen werden.

Öffentlichkeit

Jeder kann es sehen.

Veröffentlicht

Sichtbar außerhalb des Codes, den ich kontrolliere. (Dies ist zwar nicht die Java-Syntax, aber wichtig für diese Diskussion).

C ++ definiert eine zusätzliche Stufe namens "Freund" und je weniger Sie darüber wissen, desto besser.

Wann solltest du was benutzen? Die ganze Idee ist Verkapselung, um Informationen zu verbergen. So viel wie möglich möchten Sie das Detail verbergen, wie etwas von Ihren Benutzern ausgeführt wird. Warum? Denn dann kannst du sie später ändern und niemandes Code kaputt machen. Dadurch können Sie Bugs optimieren, umgestalten, neu gestalten und beheben, ohne befürchten zu müssen, dass jemand den überholten Code verwendet.

Faustregel ist also, Dinge nur so sichtbar zu machen, wie sie sein müssen. Beginnen Sie mit privat und fügen Sie nur bei Bedarf mehr Sichtbarkeit hinzu. Veröffentlichen Sie nur das, was für den Benutzer absolut notwendig ist, jedes Detail, das Sie öffentlich machen, verkrampft Ihre Fähigkeit, das System neu zu gestalten.

Wenn Sie möchten, dass Benutzer Verhaltensweisen anpassen können, anstatt Interna öffentlich zu machen, damit sie diese überschreiben können, ist es oft eine bessere Idee, diese Eingeweide in ein Objekt zu schieben und diese Schnittstelle öffentlich zu machen. Auf diese Weise können sie einfach ein neues Objekt einstecken. Wenn Sie beispielsweise einen CD-Player schreiben und das Bit "Informationen zu dieser CD suchen" möchten, anstatt diese Methoden öffentlich zu machen, würden Sie all diese Funktionen in ein eigenes Objekt einfügen und Ihr Objekt Getter / Setter öffentlich machen . Auf diese Art und Weise geizig zu sein, um Ihre Eingeweide freizulegen, fördert eine gute Zusammensetzung und Trennung von Sorgen

Persönlich bleibe ich bei "privat" und "öffentlich". Viele OO-Sprachen haben das nur. "Geschützt" kann praktisch sein, aber es ist wirklich ein Betrüger. Sobald eine Schnittstelle mehr als nur privat ist, liegt sie außerhalb Ihrer Kontrolle und Sie müssen in den Code anderer Leute schauen, um Verwendungen zu finden.

Hier kommt die Idee von "published" ins Spiel. Das Ändern einer Schnittstelle (Refactoring) erfordert, dass Sie den gesamten Code, der sie benutzt, finden und ändern können. Wenn die Schnittstelle privat ist, ist das kein Problem. Wenn es geschützt ist, musst du alle deine Unterklassen finden. Wenn es öffentlich ist, musst du den ganzen Code finden, der deinen Code benutzt. Manchmal ist dies möglich, wenn Sie beispielsweise an Unternehmenscode arbeiten, der nur für den internen Gebrauch bestimmt ist, spielt es keine Rolle, ob eine Schnittstelle öffentlich ist. Sie können den gesamten Code aus dem Unternehmens-Repository abrufen. Aber wenn eine Schnittstelle "veröffentlicht" wird, wenn Sie Code außerhalb Ihrer Kontrolle verwenden, dann werden Sie abgespritzt. Sie müssen diese Schnittstelle oder diesen Code unterstützen. Selbst geschützte Schnittstellen können als publiziert gelten (weshalb ich mich nicht mit geschützten beschäftige).

Viele Sprachen empfinden die hierarchische Natur von öffentlich / geschützt / privat als zu einschränkend und nicht im Einklang mit der Realität. Zu diesem Zweck gibt es das Konzept von a Merkmalsklasse, aber das ist eine andere Show.


357
2017-10-18 21:17



Hier ist eine bessere Version der Tabelle. (Zukunftssicher mit einer Spalte für Module.)

Java Access Modifiers

Erklärungen

  • EIN Privatgelände Mitglied ist nur zugänglich innerhalb derselben Klasse, wie sie deklariert ist.

  • Ein Mitglied mit kein Zugriffsmodifizierer ist nur innerhalb von Klassen im selben Paket verfügbar.

  • EIN geschützt member ist in allen Klassen desselben Pakets verfügbar und innerhalb von Unterklassen in anderen Paketen.

  • EIN Öffentlichkeit Das Mitglied ist für alle Klassen zugänglich (außer es befindet sich in einem Modul das exportiert das Paket nicht, in dem es deklariert wird).


Welcher Modifikator soll gewählt werden?

Access Modifiers ist ein Tool, mit dem Sie verhindern können, dass die Kapselung versehentlich unterbrochen wird(*). Fragen Sie sich, ob Sie das Mitglied als internes Element der Klasse, des Pakets, der Klassenhierarchie oder überhaupt nicht intern definieren möchten, und wählen Sie entsprechend die Zugriffsebene aus.

Beispiele:

  • Ein Feld long internalCounter sollte wahrscheinlich privat sein, da es veränderbar ist und ein Implementierungsdetail.
  • Eine Klasse, die nur in einer Factory-Klasse (im selben Paket) instanziiert werden sollte, sollte einen Konstruktor mit eingeschränktem Paket haben, da es nicht möglich sein sollte, sie direkt von außerhalb des Pakets aufzurufen.
  • Eine interne void beforeRender() Methode, die direkt vor dem Rendern aufgerufen wird und als Hook in Unterklassen verwendet wird, sollte geschützt werden.
  • EIN void saveGame(File dst) Methode, die aus dem GUI-Code aufgerufen wird, sollte öffentlich sein.

(*) Was ist Kapselung genau?


243
2017-11-10 10:27



                | 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         |              |     ✘     |       ✘       |   ✘    

165
2018-01-09 21:42



Einfache Regel. Beginnen Sie damit, alles für privat zu erklären. Und dann Fortschritte in Richtung der Öffentlichkeit, wie die Bedürfnisse entstehen und Design es rechtfertigt.

Wenn Sie Mitglieder exponieren, fragen Sie sich, ob Sie Repräsentationsmöglichkeiten oder Abstraktionswahlen offen legen. Das erste ist etwas, das Sie vermeiden möchten, da es zu viele Abhängigkeiten von der tatsächlichen Repräsentation und nicht von ihrem beobachtbaren Verhalten einführt.

Als allgemeine Regel versuche ich zu vermeiden, dass Methodenimplementierungen durch Unterklassen überschrieben werden; es ist zu leicht, die Logik zu vermasseln. Deklarieren Sie abstrakte geschützte Methoden, wenn Sie beabsichtigen, sie zu überschreiben.

Verwenden Sie außerdem beim Überschreiben die Annotation @Override, um zu verhindern, dass die Elemente beim Refactoring beschädigt werden.


130
2017-10-18 20:00



Es ist tatsächlich ein bisschen komplizierter als ein einfaches Raster zeigt. Das Grid sagt Ihnen, ob ein Zugriff zulässig ist, aber was genau einen Zugriff darstellt. Außerdem interagieren Zugriffsebenen auf komplexe Weise mit verschachtelten Klassen und Vererbung.

Der "Standard" -Zugriff (angegeben durch das Fehlen eines Schlüsselworts) wird ebenfalls aufgerufen Paket-privat. Ausnahme: In einer Schnittstelle bedeutet kein Modifikator öffentlichen Zugriff; Modifikatoren außer der Öffentlichkeit sind verboten. Enum-Konstanten sind immer öffentlich.

Zusammenfassung

Ist ein Zugriff auf ein Mitglied mit diesem Zugriffsspezifizierer zulässig?

  • Mitglied ist private: Nur wenn Mitglied in derselben Klasse wie der aufrufende Code definiert ist.
  • Mitglied ist Paket privat: Nur wenn sich der aufrufende Code im umschließenden Paket des Mitglieds befindet.
  • Mitglied ist protected: Gleiches Paket oder wenn Mitglied in einer Oberklasse der Klasse definiert ist, die den aufrufenden Code enthält.
  • Mitglied ist public: Ja.

Welche Zugriffsspezifizierer gelten für?

Lokale Variablen und formale Parameter können keine Zugriffsspezifizierer enthalten. Da sie nach den Scoping-Regeln von Natur aus nicht zugänglich sind, sind sie effektiv privat.

Nur für Klassen im oberen Bereich public und package-private sind erlaubt. Diese Designwahl ist vermutlich weil protected und private wäre auf der Paketebene redundant (es gibt keine Vererbung von Paketen).

Alle Zugriffsspezifizierer sind für Klassenmitglieder (Konstruktoren, Methoden und statische Elementfunktionen, verschachtelte Klassen) möglich.

Verbunden: Java-Klassenzugänglichkeit

Auftrag

Die Zugriffsspezifizierer können streng geordnet werden

öffentlich> geschützt> paket-privat> privat

bedeutet, dass public bietet den meisten Zugriff, private das Mindeste. Jede Referenz, die auf einem privaten Mitglied möglich ist, gilt auch für ein paket-privates Mitglied; Jeder Verweis auf ein privates Paket-Mitglied ist für ein geschütztes Mitglied gültig und so weiter. (Der Zugriff auf geschützte Mitglieder auf andere Klassen im selben Paket wurde als Fehler angesehen.)

Anmerkungen

  • Die Methoden einer Klasse sind darf auf private Mitglieder anderer Objekte derselben Klasse zugreifen. Genauer gesagt kann eine Methode der Klasse C auf Objekte jeder Unterklasse von C auf private Member von C zugreifen. Java unterstützt nicht die Einschränkung des Zugriffs nach Instanz, nur nach Klasse. (Vergleichen Sie mit Scala, das unterstützt es mit private[this].)
  • Sie benötigen Zugriff auf einen Konstruktor, um ein Objekt zu konstruieren. Wenn also alle Konstruktoren privat sind, kann die Klasse nur durch Code konstruiert werden, der innerhalb der Klasse lebt (typischerweise statische Factory-Methoden oder statische Variableninitialisierungen). Ähnlich für Paket-private oder geschützte Konstruktoren.
    • Nur private Konstruktoren zu haben bedeutet auch, dass die Klasse nicht extern unterkonsolidiert werden kann, da Java die Konstruktoren einer Unterklasse benötigt, um einen Superklassenkonstruktor implizit oder explizit aufzurufen. (Sie kann jedoch eine verschachtelte Klasse enthalten, die sie unterklassifiziert.)

Innere Klassen

Sie müssen auch darüber nachdenken verschachtelt Bereiche wie innere Klassen. Ein Beispiel für die Komplexität ist, dass innere Klassen Mitglieder haben, die selbst Zugriffsmodifizierer nehmen können. So können Sie eine private innere Klasse mit einem öffentlichen Mitglied haben; Kann auf das Mitglied zugegriffen werden? (Siehe unten.) Die allgemeine Regel besteht darin, den Bereich zu betrachten und rekursiv zu denken, um zu sehen, ob Sie auf jede Ebene zugreifen können.

Dies ist jedoch ziemlich kompliziert und für alle Details Konsultieren Sie die Java-Sprachspezifikation. (Ja, in der Vergangenheit gab es Compilerfehler.)

Um einen Eindruck davon zu gewinnen, wie diese interagieren, betrachten Sie dieses Beispiel. Es ist möglich, private innere Klassen "auszulecken"; Dies ist normalerweise eine Warnung:

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();
    }
}

Compiler-Ausgabe:

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

Einige verwandte Fragen:


94
2017-09-13 07:38



Als Faustregel gilt:

  • Privatgelände: Klassenumfang
  • Standard (oder Paket-privat): Paketumfang.
  • geschützt: Paketumfang + Kind (wie Paket, aber wir können es von verschiedenen Paketen ableiten). Der geschützte Modifizierer behält immer die "Eltern-Kind" -Beziehung bei.
  • Öffentlichkeit: überall.

Wenn wir das Zugriffsrecht in drei Rechte unterteilen:

  • (Direkte (Aufruf von einer Methode innerhalb derselben Klasse).
  • (Referenz (Rufen Sie eine Methode auf, die einen Verweis auf die Klasse oder die "Punkt" -Syntax verwendet).
  • (Erbe (über Unterklasse).

dann haben wir diese einfache Tabelle:

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

63
2017-12-18 18:01



In sehr kurzer Zeit

  • public: von überall zugänglich.
  • protected: Zugänglich für die Klassen desselben Pakets und die in jedem Paket enthaltenen Unterklassen.
  • Standard (kein Modifikator angegeben): Zugänglich für die Klassen desselben Pakets.
  • private: nur in derselben Klasse zugänglich.

43
2017-10-27 17:49



Der am meisten missverstandene Zugriffsmodifikator in Java ist protected. Wir wissen, dass es dem Standardmodifikator ähnelt, mit einer Ausnahme, in der Unterklassen es sehen können. Aber wie? Hier ist ein Beispiel, das hoffentlich die Verwirrung klärt:

  • Angenommen, wir haben 2 Klassen; Father und Son, jedes in seinem eigenen Paket:

    package fatherpackage;
    
    public class Father
    {
    
    }
    
    -------------------------------------------
    
    package sonpackage;
    
    public class Son extends Father
    {
    
    }
    
  • Lassen Sie uns eine geschützte Methode hinzufügen foo() zu Father.

    package fatherpackage;
    
    public class Father
    {
        protected void foo(){}
    }
    
  • Die Methode foo() kann in 4 Kontexten aufgerufen werden:

    1. Innerhalb einer Klasse, die sich im selben Paket befindet foo() ist definiert (fatherpackage):

      package fatherpackage;
      
      public class SomeClass
      {
          public void someMethod(Father f, Son s)
          {
              f.foo();
              s.foo();
          }
      }
      
    2. Innerhalb einer Unterklasse, in der aktuellen Instanz via this oder super:

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod()
          {
              this.foo();
              super.foo();
          }
      }
      
    3. Bei einer Referenz, deren Typ dieselbe Klasse ist:

      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. Auf eine Referenz, deren Typ die Elternklasse ist und es ist Innerhalb das Paket wo foo() ist definiert (fatherpackage) [Dies kann innerhalb des Kontext-Nr. 1]:

      package fatherpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo();
          }
      }
      
  • Die folgenden Situationen sind nicht gültig.

    1. Auf eine Referenz, deren Typ die Elternklasse ist und es ist draußen das Paket wo foo() ist definiert (fatherpackage):

      package sonpackage;
      
      public class Son extends Father
      {
          public void sonMethod(Father f)
          {
              f.foo(); // compilation error
          }
      }
      
    2. Eine Nicht-Unterklasse in einem Paket einer Unterklasse (Eine Unterklasse erbt die geschützten Elemente von ihrem übergeordneten Element und macht sie für Nicht-Unterklassen privat):

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

32
2017-11-15 20:06



Privatgelände

  • Methoden, Variablen und Konstruktoren

Auf Methoden, Variablen und Konstruktoren, die als privat deklariert sind, kann nur innerhalb der deklarierten Klasse selbst zugegriffen werden.

  • Klasse und Schnittstelle

Der private Zugriffsmodifikator ist die restriktivste Zugriffsebene. Klasse und Schnittstellen können nicht privat sein.

Hinweis

Auf Variablen, die als privat deklariert sind, kann außerhalb der Klasse zugegriffen werden, wenn in der Klasse öffentliche Getter-Methoden vorhanden sind. Auf Variablen, Methoden und Konstruktoren, die in einer Oberklasse als geschützt deklariert sind, kann nur von den Unterklassen in einem anderen Paket oder einer Klasse innerhalb des Pakets der Klasse der geschützten Mitglieder zugegriffen werden.


Geschützt

  • Klasse und Schnittstelle

Der Modifikator für den geschützten Zugriff kann nicht auf Klassen und Schnittstellen angewendet werden.

Methoden, Felder können als geschützt deklariert werden, jedoch können Methoden und Felder in einer Schnittstelle nicht als geschützt deklariert werden.

Hinweis

Geschützter Zugriff gibt der Unterklasse die Möglichkeit, die Hilfsmethode oder -variable zu verwenden, während sie verhindert, dass eine nicht verwandte Klasse versucht, sie zu verwenden.


Öffentlichkeit

Auf eine deklarierte Klasse class, method, constructor, interface etc. kann von jeder anderen Klasse zugegriffen werden. 

Daher kann auf Felder, Methoden, Blöcke, die innerhalb einer öffentlichen Klasse deklariert sind, von jeder Klasse zugegriffen werden, die zum Java-Universum gehört.

  • Verschiedene Pakete

Wenn die öffentliche Klasse, auf die wir zugreifen möchten, sich jedoch in einem anderen Paket befindet, muss die öffentliche Klasse noch importiert werden.

Aufgrund der Klassenvererbung werden alle öffentlichen Methoden und Variablen einer Klasse von ihren Unterklassen geerbt.


Standard - Kein Schlüsselwort:

Standardzugriffsmodifikator bedeutet, dass wir einen Zugriffsmodifizierer für eine Klasse, ein Feld, eine Methode usw. nicht explizit deklarieren.

  • Innerhalb der gleichen Pakete

Eine Variable oder Methode, die ohne Zugriffsmodifizierer deklariert wurde, ist für jede andere Klasse im selben Paket verfügbar. Die Felder in einer Schnittstelle sind implizit öffentlich statisch und die Methoden in einer Schnittstelle sind standardmäßig öffentlich.

Hinweis

Wir können die statischen Felder nicht überschreiben. Wenn Sie versuchen, sie zu überschreiben, wird kein Fehler angezeigt aber es funktioniert nicht, was wir außer.

Verwandte Antworten

Referenzen Links

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


24
2018-01-22 13:08