javaseiten.de   |   Version 0.6
 

1.6. Modifier und Sichtbarkeit

Klassen, Felder und Methoden können mit Modifiern, z.B. mit public, deklariert werden. Ein Modifier legt dabei die Sichtbarkeit (scope) der Klasse, des Feldes bzw. der Methode fest. Bei entsprechender Deklaration kann eine Klasse z.B. nur innerhalb eines Pakets genutzt werden (sie ist nur innerhalb des Pakets "sichtbar"). Die Sichtbarkeit von Methoden und Feldern, ist im Sinne des Aufrufs einer Methode bzw. eines Feldzugriffs zu verstehen. In den folgenden Unterabschnitten werden verschiedene Java-Quelltexte vorgestellt, um die Thematik Sichtbarkeit zu erläutern. Die einzelnen Beispielprogramme befinden sich dabei in unterschiedlichen Ordnern. Die im Unterordner p1 stehenden Dateien sollen zu einem Paket p1 gehören. Die Datei Test.java befindet sich in einem geeigneten Verzeichnis und soll dem Default-Paket (unnamed package, der Quelltext enthält keine package-Deklaration) angehören.

Ausgangsverzeichnis:    Test.java
Ausgangsverzeichnis/p1: ScopeExample.java
                        ScopeExample2.java
                        ScopeExample3.java
                        TestP1.java

1.6.1. Klassen

Bei Klassen wird zwischen Top-Level-Klassen und eingebetteten Klassen unterschieden. Dabei ist eine eingebettete Klasse eine Klasse, die innerhalb eines Körpers einer anderen Klasse deklariert ist (siehe dazu Abschnitt 1.10). Im Gegensatz zu Feldern und Methoden können Top-Level-Klassen nur mit dem Modifier public und nicht mit protected oder private deklariert werden. Top-Level-Klassen können auch ohne einen Modifier deklariert werden. Dies führt dazu, dass eine Sichtbarkeit einer solchen Klasse nur innerhalb des Pakets besteht. Die Angabe von public bei der Deklaration erhöht die Sichtbarkeit der Klasse. Sie ist dann auch von anderen Paketen aus nutzbar. Das folgende Beispiel beginnt mit dem Schlüsselwort package. Die Klasse ScopeExample soll dem Paket p1 angehören und der zugehörige Quelltext steht im Unterverzeichnis p1. Die Klasse ist als public deklariert.

Listing 1.22. ScopeExample.java. Deklaration der Beispielklasse mit dem Modifier public.

/* ScopeExample.java */

package p1;

public class ScopeExample {
  
  int a;
  public int b;
  protected int c;
  private int d;
  
  void method1() {
    System.out.println("method1");
  }

  public void method2() {
    System.out.println("method2");
  }
  
  protected void method3() {
    System.out.println("method3");
  }
  
  private void method4() {
    System.out.println("method4");
  }
}

Der zweite Java-Quelltext zum Beispiel legt die Klasse ScopeExample2 fest. Sie soll ebenfalls dem Paket p1 zugeordnet werden. Die Klassendeklaration enthält im Gegensatz zum vorhergehenden Listing keinen Klassenmodifier. Dies führt zu einer eingeschränkten Sichtbarkeit der Klasse, wie die noch folgenden kurzen Testprogramme zeigen werden.

Listing 1.23. ScopeExample2.java. Klasse mit eingeschränkter Sichtbarkeit (Paket-Sichtbarkeit).

/* ScopeExample2.java */

package p1;

class ScopeExample2 {
  
  int a;

  void method1() {
    System.out.println("method21");
  }
}

Das kurze Testprogramm Test.java befindet sich direkt im gewählten Ausgangsverzeichnis und ist dem Default-Paket zuzuordnen. Innerhalb der main-Methode soll versucht werden, Objekte der Klassen ScopeExample und ScopeExample2 zu beschaffen. Die beiden genannten Klassen befinden sich in einem anderen Paket als Test. Es zeigt sich, dass die Erzeugung eines Objekts der Klasse ScopeExample2 fehlschlägt. Der Compiler moniert, dass die Klasse ohne Klassenmodifier vom Default-Paket aus nicht zugänglich ist.

/* Test.java */

public class Test {

  public static void main(String[] args) {
   
    p1.ScopeExample se = new p1.ScopeExample();
    
    p1.ScopeExample2 se2 = new p1.ScopeExample2();
    // Fehler (Compiler): p1.ScopeExample2 is not public in p1; 
    // cannot be accessed from outside package
  }
}

Im Gegensatz zu Test.java befindet sich das zweite Testprogramm TestP1.java im Unterordner p1. Die Klassen TestP1, ScopeExample und ScopeExample2 befinden sich also im gleichen Paket. Die Erzeugung eines Objekts von ScopeExample2 gelingt in diesem Fall ohne Probleme.

/* TestP1.java */

package p1;

public class TestP1 {

  public static void main(String[] args) {
    ScopeExample se = new ScopeExample();
    ScopeExample2 se2 = new ScopeExample2();
  }
}


Ausgangsverzeichnis> javac p1/TestP1.java
Ausgangsverzeichnis> java p1.TestP1

1.6.2. Felder und Methoden

Die Programmiersprache Java stellt verschiedene Zugriffsebenen zur Verfügung, zu denen Methoden und Felder zugeordnet werden können. Zugriffsebenen können sinnvoll sein, um z.B. Aufrufe von bestimmten Methoden zu verhindern. Die unterschiedlichen Ebenen werden durch Modifier (public, protected bzw. private) festgelegt, welche bei der Deklaration von Feldern bzw. Methoden verwendet werden. Die anschließenden vier Aussagen zu den Zugriffsebenen sollen anhand später folgenden Beispielen erläutert werden.

  • Standardzugang. Bei der Deklaration des Feldes bzw. der Methode wurde keiner der Modifier public, protected bzw. private verwendet. Der Zugriff auf das Feld bzw. der Aufruf der Methode ist eingeschränkt (kein Zugang von außerhalb des Pakets: Paket-Sichtbarkeit, der Zugang innerhalb der selben Klasse ist gewährleistet).

  • Zugang mit public. Erfolgt die Deklaration eines Feldes bzw. einer Methode mit public ist der Zugang des Feldes bzw. der Methode auch von außerhalb des Pakets möglich (der Zugang innerhalb der selben Klasse ist gewährleistet).

  • Zugang mit protected. Der Zugang zu Feldern bzw. Methoden, welcher mit dem Schlüsselwort protected eingeschränkt wurde, ist innerhalb des Pakets (Klasse) gewährleistet und ist außerhalb des Pakets nur unter bestimmten Voraussetzungen möglich: Die Klasse, innerhalb derer der Zugriff stattfinden soll, befindet sich in einem anderen Paket und erweitert die Klasse (siehe Abschnitt 1.7.2), welche das protected-Feld bzw. die protected-Methode enthält.

  • Zugang mit private. Felder und Methoden können innerhalb einer Klasse als private eingestuft werden. Der Zugang derartiger Felder und Methoden ist nur innerhalb der selben Klasse möglich.

Die nachfolgende Quelldatei Test.java kann in das gewählte Ausgangsverzeichnis kopiert werden und soll dem Default-Paket angehören. Innerhalb der main-Methode wird zunächst ein Objekt der Klasse ScopeExample aus Listing 1.22 beschafft. Anschließend wird versucht, auf die einzelnen Felder dieser Klasse zuzugreifen. Auch der Aufruf der Methoden dieser sich im Paket p1 befindlichen Klasse führt zu Fehlermeldungen, falls der Zugang der Methoden mit entsprechenden Modifiern eingeschränkt wurde.

/* Test.java */

public class Test {

  public static void main(String[] args) {
    p1.ScopeExample se = new p1.ScopeExample();
    
    se.a = 3;
    // Fehler (Compiler): a is not public in p1.ScopeExample;
    // cannot be accessed from outside package
    
    se.b = 4;
    
    se.c = 5;
    // Fehler (Compiler): c has protected access in p1.ScopeExample
    
    se.d = 6;
    // Fehler (Compiler): d has private access in p1.ScopeExample
    
    se.method1();
    // Fehler (Compiler): method1() is not public in p1.ScopeExample;
    // cannot be accessed from outside package
    
    se.method2();
    
    se.method3();
    // Fehler (Compiler): method3() has protected access in p1.ScopeExample
    
    se.method4();
    // Fehler (Compiler): method4() has private access in p1.ScopeExample
  }
}

Die Fehlermeldungen durch den Compiler zeigen, dass ein paketübergreifender Feldzugriff nur erfolgreich ist, wenn das Feld als public deklariert wurde. Ein Methodenaufruf gelingt ebenfalls nur, wenn auch die entsprechende Methode mit dem Modifier public versehen wurde. Der Aufruf von protected- bzw. private-Methoden ist nicht erfolgreich. Auch der paketübergreifende Aufruf von method1 der Klasse ScopeExample führt zu einer Fehlermeldung, da die Methode ohne Modifier angegeben wurde und damit nur Paket-Sichtbarkeit besitzt.

Der Quelltext Test.java kann geändert werden, um auch protected-Zugriffe zu ermöglichen. Dazu kann die Klasse Test des Default-Pakets die Klasse ScopeExample des Pakets p1 ableiten (siehe Abschnitt 1.7.2). Innerhalb der statischen Hauptmethode kann nun eine Objekt von Test erzeugt werden und damit kann auf das protected-Feld c zugegriffen werden. Auch der Aufruf der protected-Methode ist nun erfolgreich.

/* Test.java */

public class Test extends p1.ScopeExample {

  public static void main(String[] args) {
    Test t = new Test();
    t.c = 5;
    t.method3();
  }
}

Mit Test.java wurde der Feldzugriff bzw. Methodenaufruf paketübergreifend durchgeführt. Mit Listing TestP1.java sollen die Zugriffe bzw. Aufrufe innerhalb des Pakets erfolgen. Dazu kann die Datei TestP1.java im Unterverzeichnis p1 erstellt werden. Das Testprogramm beginnt mit dem Schlüsselwort package und der folgenden Angabe p1. Die Klassen TestP1 und ScopeExample gehören nun dem selben Paket an. Alle Feldzugriffe sind bis auf das private-Feld erfolgreich. Auch bei den Methodenaufrufen ist nur der Aufruf der private-Methode erfolglos.

/* TestP1.java */

package p1;

public class TestP1 {

  public static void main(String[] args) {
    ScopeExample se = new ScopeExample();
    
    se.a = 3;
    se.b = 4;
    se.c = 5;
    
    se.d = 6;
    // Fehler (Compiler): d has private access in p1.ScopeExample
    
    se.method1();
    se.method2();
    se.method3();
        
    se.method4();
    // Fehler (Compiler): method4() has private access in p1.ScopeExample
  }
}

Auf private Felder und Methoden kann innerhalb derselben Klassen zugegriffen werden. Die Deklaration von method2 aus Listing 1.22 kann ergänzt werden, um z.B. die private Methode method4 aufzurufen.

public void method2() {
  System.out.println("method2");
  method4();
}

1.6.3. Konstruktoren

Ebenso wie bei Methoden können Konstruktoren mit den Modifiern public, protected oder private deklariert werden. Auch eine Deklaration eines Konstruktors ohne die Angabe eines der genannten Modifier ist zulässig. Das Beispiel ScopeExample3.java deklariert insgesamt vier Konstruktoren mit unterschiedlichen Zugangsberechtigungen. Die Klasse ScopeExample3 soll dem Paket p1 angehören.

Listing 1.24. ScopeExample3.java. Konstruktoren mit unterschiedlichen Zugangsberechtigungen.

/* ScopeExample3.java */

package p1;

public class ScopeExample3 {
  
  int a;
  int b;
  int c;
  int d;
  
  ScopeExample3(int a) {
    this.a = a;
  }
  
  public ScopeExample3(int a, int b) {
    this.a = a;
    this.b = b;
  }
  
  protected ScopeExample3(int a, int b, int c) {
    this.a = a;
    this.b = b;
    this.c = c;
  }
  
  private ScopeExample3(int a, int b, int c, int d) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.d = d;
  }
  
  public static void main(String[] args) {
    ScopeExample3 se = new ScopeExample3(3, 4, 5, 6); 
  }
}

Test soll im Gegensatz zu ScopeExampl3 dem Default-Paket zugeordnet sein. Innerhalb der main-Methode des Testprogramms soll ein Objekt der Klasse ScopeExample3 erzeugt werden. Dazu werden die unterschiedlichen Konstruktoren mit unterschiedlichen Zugangsberechtigungen aufgerufen. Es zeigt sich, dass eine paketübergreifende Objekterzeugung nur mit dem public-Konstruktor gelingt.

/* Test.java */

public class Test {

  public static void main(String[] args) {
    p1.ScopeExample3 se = new p1.ScopeExample3(3);
    // Fehler (Compiler): cannot find constructor ScopeExample3(int)
    
    p1.ScopeExample3 se2 = new p1.ScopeExample3(3, 4);
    
    p1.ScopeExample3 se3 = new p1.ScopeExample3(3, 4, 5);
    // Fehler (Compiler): cannot find constructor ScopeExample3(int,int,int)
    
    p1.ScopeExample3 se4 = new p1.ScopeExample3(3, 4, 5, 6);
    // Fehler (Compiler): ScopeExample3(int,int,int,int) has private access
    // in p1.ScopeExample3
  }
}

Die einzelnen Konstruktoraufrufe sollen nun innerhalb desselben Pakets erfolgen. Dazu kann die Datei TestP1.java erstellt werden und in das Unterverzeichnis p1 kopiert werden. Bis auf den private-Konstruktor mit vier Parametern können nun alle Konstruktoren zur Objekterzeugung genutzt werden. Der Aufruf des private-Konstruktors ist hingegen innerhalb der Hauptmethode aus Listing 1.24 erfolgreich.

/* TestP1.java */

package p1;

public class TestP1 {

  public static void main(String[] args) {
    ScopeExample3 se = new ScopeExample3(3);
    ScopeExample3 se2 = new ScopeExample3(3, 4);
    ScopeExample3 se3 = new ScopeExample3(3, 4, 5);
        
    ScopeExample3 se4 = new ScopeExample3(3, 4, 5, 6);
    // Fehler (Compiler): ScopeExample3(int,int,int,int) has private access 
    // in p1.ScopeExample3
  
  }
}

 

 

 

Diese Seite nutzt Google-Dienste - siehe dazu Datenschutz.

Copyright © 2006, 2007 Harald Roeder