Gültigkeitsbereiche in Java (Gültigkeitsbereiche in Java), Lektion, Seite 723812
https://www.purl.org/stefan_ram/pub/gueltigkeitsbereich_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Java-Kurs

Gültigkeitsbereiche in Java 

Der Begriff „Gültigkeitsbereich“ ist ein Begriff des Quelltextmodells.

Der Teil des Quelltextes, in welchem zur Ermittlung der Bedeutung einer Verwendung eines Name (ohne Qualifikation) eine bestimmte Deklaration herangezogen wird, wird der Gültigkeitsbereich  jener Deklaration genannt. Wenn keine Mißverständnisse möglich sind, spricht man auch vom Gültigkeitsbereich des (in jener Deklaration deklarierten) Namens  oder der Variablen.

Der Gültigkeitsbereich der Deklaration einer innerhalb eines Blocks deklarierten Variablen reicht von der Stelle direkt nach dem Gleichheitszeichen in der Deklaration bis zum Ende des innersten die Deklaration direkt enthaltenden Blocks.

Die Variablendeklaration »final int zwoelf = 12;« bedeutet, daß der Bezeichner »zwoelf« in seinem Gültigkeitsbereich (also im Rest des Blockes) als Ausdruck mit dem Typ »int« und dem Wert »12« verwendet werden können soll.

Erneute Deklarationen

In einem Block darf jeder Name nur einmal  deklariert werden.

Main.txt
public final class Main
{ public static void main( java.lang.String[] args )
{ final int i = 22; java.lang.System.out.println( i );
final int i = 22; java.lang.System.out.println( i );
}}
Protokoll
Main.java:4: error: variable i is already defined in method main(String[])
final int i = 22; java.lang.System.out.println( i ); }}
^
1 error

Bei Fehlern durch unerlaubte Mehrfachdeklaration ein und desselben Namens spricht man auch von einem Zusammenstoß  oder einer Kollision  der Namen (Namenskollision).

Begrenzungen der Gültigkeit im Quelltext

Eine Deklaration gilt nur für den Rest des sie direkt enthaltenden Blocks  (ab dem Gleichheitszeichen). Da der Gültigkeitsbereich einer solchen in einem Block deklarierten Variablen auf den relativ kleinen Bereich des Blockes eingeschränkt ist, wird solch eine Deklaration auch eine lokale Deklaration  und solch eine Variable auch eine lokale Variable  genannt.

Main.txt

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int n = 7;
java.lang.System.out.println( n );
}

java.lang.System.out.println( n ); }}

Protokoll
Main.txt:8: error: cannot find symbol
java.lang.System.out.println( n ); }}
^
symbol: variable n
location: class Main
1 error

Entsprechend darf eine in einem inneren Block schon einmal deklarierte Variable in einem äußeren Block deklariert werden, wenn sich die Deklaration in dem äußeren Block hinter der Deklaration in dem inneren Block befindet.

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int n = 7;
java.lang.System.out.println( n );
}

final int n = 4;
java.lang.System.out.println( n );
}}

Protokoll
7
4

Wir behandeln in dieser Lektion nur innerhalb eines Blocks  deklarierte Variablen, die wir auch manchmal Blockvariablen  nennen.

Man sagt auch, daß man durch eine Deklaration einen Namen in einen Gültigkeitsbereich oder einen Block einführe  (im Sinne von „Hinzufügen“), oder man sagt zu einer Festlegung einer Variablen auch „Einführung  einer Variablen“.

Nichtüberlappende Gültigkeitsbereiche

Blöcke können einander folgen. Jeder Block ist ein eigener Namensraum  und kann daher eigene lokale Variablen  enthalten, deren Namen sich nicht von den Namen lokaler Variablen in anderen nicht-überlappenden Gültigkeitsbereichen unterscheiden müssen.

final-Variablen werden ja manchmal auch als „Konstanten“ bezeichnet. Man könnte dazu einwenden, die Konstante »i« sei hier gar keine richtige Konstante, da sie zuerst 3 und dann 7 sei. Tatsächlich handelt es sich hierbei aber um zwei verschiedene  Konstanten, die nur den gleichen Bezeichner »i« miteinander teilen. Sie sind aber unterschiedliche Konstanten, da sie in zwei unterschiedlichen, nichtüberlappenden Gültigkeitsbereichen existieren.

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{ /*

.------------------------------------.
| |
| v */
{ final int i = 3; java.lang.System.out.println( i ); } /*

.------------------------------------.
| |
| v */
{ final int i = 7; java.lang.System.out.println( i ); }

}}

Protokoll
3
7

Die Identität einer Variablen ist erst durch ihren Namen und ihren Gültigkeitsbereich  gemeinsam gegeben. Zwei Variablen mit unterschiedlichen Gültigkeitsbereichen sind also zwei verschiedene  Variablen, auch wenn sie denselbe Namen haben.

Wenn der Gültigkeitsbereich eines Namens klein  ist (wie in dem obigen Programmbeispiel), ist es eher möglich, daß der Name bei Bedarf in verschiedenen Programmteilen verwendet werden kann, ohne daß es zu Namenskollisionen kommt. Daher sollte der Gültigkeitsbereich eines Namens immer möglichst klein  sein.

Verschachtelte Bereiche

Ein innerer Block ist ein eigener Gültigkeitsbereich. Er übernimmt („erbt“) alle Deklarationen umgebender Gültigkeitsbereiche, schließlich ist er ja im wörtlichen Sinne in diesen enthalten, also Teil von ihnen.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final int i = 22; { java.lang.System.out.println( i ); }}}
java.lang.System.out
22

In einem inneren Block dürfen lokale Bezeichner eines äußeren Blocks nicht  erneut deklariert werden.

Main.txt
public final class Main
{ public static void main( java.lang.String[] args )
{ final int i = 22;
{ final int i = 23; java.lang.System.out.println( i ); }
}}
Protokoll
Main.java:4: error: variable i is already defined in method main(String[])
{ final int i = 23; java.lang.System.out.println( i ); }}}
^
1 error

Richtung einer Deklaration ⃗

Eine lokale Variable kann nicht vor  der Stelle ihrer Deklaration verwendet werden, auch wenn die Verwendung im selben Block erfolgt.

Main.txt
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( i ); final int i = 22; }}
Protokoll
Main.java:3: error: cannot find symbol
{ java.lang.System.out.println( i ); final int i = 22; }}
^
symbol: variable i
location: class Main
1 error

Unterscheidung zu Namen aus Klassen ⃗

Es ist erlaubt, einen Namen, der schon in einer Klasse der Standardbibliothek deklariert wurde, in einem Block erneut zu deklarieren.

Der Block in dem folgenden Programm gehört nicht zum Gültigkeitsbereich des Namens »PI« aus der Klasse »java.lang.Math«, da der Name im Block nicht ohne Qualifikation verwendet werden kann. Daher kann in diesem Block ein lokaler Name »PI« deklariert werden. Durch die Qualifikation können beiden Namen danach unterschieden werden.

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

final double PI = 3.1415926535897932384626433832795;

java.lang.System.out.println( PI );

java.lang.System.out.println( java.lang.Math.PI ); }}

transcript
3.141592653589793
3.141592653589793

Anders als in dem obigen Beispielprogramm gezeigt, sollten aber in einem Block deklarierte final-Variablen normalerweise nicht  groß geschrieben werden.

Übungsfragen ⃗

?   Gültigkeitsbereiche ⃗

Kann das folgende Programm ohne Fehlermeldungen gestartet werden, und was gibt es dann gegebenenfalls aus?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int i = 4; java.lang.System.out.println( i ); }

{ final int j = 1; java.lang.System.out.println( j ); } }}

?   Gültigkeitsbereiche ⃗

Kann das folgende Programm ohne Fehlermeldungen gestartet werden, und was gibt es dann gegebenenfalls aus?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int i = 5; java.lang.System.out.println( i ); }

{ final int i = 0; java.lang.System.out.println( i ); } }}

?   Gültigkeitsbereiche ⃗

Kann das folgende Programm ohne Fehlermeldungen gestartet werden, und was gibt es dann gegebenenfalls aus?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

{ final int i = 2; java.lang.System.out.println( i ); }

final int i = 4; java.lang.System.out.println( i ); }}

?   Gültigkeitsbereiche ⃗

Kann das folgende Programm ohne Fehlermeldungen gestartet werden, und was gibt es dann gegebenenfalls aus?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

final int i = 7; java.lang.System.out.println( i );

{ final int i = 8; java.lang.System.out.println( i ); } }}

?   Gültigkeitsbereiche ⃗

Kann das folgende Programm ohne Fehlermeldungen gestartet werden, und was gibt es dann gegebenenfalls aus?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

final int i = 8; java.lang.System.out.println( i );

{ java.lang.System.out.println( i ); } }}

Übungsaufgaben ⃗

/   Refaktor ⃗

Setzen Sie die beiden Paare von Anweisungen, die im folgenden Programm enthalten sind, jeweils in geschweifte Klammern und benennen Sie »text1« dann in »text« um. Vergewissern Sie sich, daß das Programm hinterher weiterhin mit derselben Ausgabe läuft.

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )
{

final java.lang.String text = "text";
java.lang.System.out.println( text );

final java.lang.String text1 = "text";
java.lang.System.out.println( text1 );

}}

transcript
text
text

(Wenn sich in einem Programmteil eine Beinahe-Wiederholung eines Programmteils findet, sollte diese in eine wörtliche Wiederholung umgewandelt werden. In manchen Fällen ist es dann nämlich möglich, die beiden Wiederholungen zu einem Programmteil zusammenzufassen, wie später zu sehen sein wird.)

Ein Anwendungsbeispiel *

Wenn Büromöbel von einem Endverbraucher erworben werden, sind im Jahre 2003 noch 16 % Mehrwertsteuer zu zahlen. Es werden zwei Tische für je 420 Euro und eine Lampe für 145 Euro Warenwert erworben und 3 % Rabatt vereinbart. Wieviel Euro sind zu zahlen?

Main.java

public final class Main
{ public static void main( final java.lang.String[] args )

{ // ewige Konstanten; "Welt"
final double prozent = 0.01;
final double euro = 1.;

{ // aktuelle Konstanten; "Bundesrepublik Deutschland"
final double mwSt = 16. * prozent;

{ // Warenwerte (Preisliste); "Dieses Geschäft"
final double tischwert = 420 * euro;
final double lampenwert = 145 * euro;

{ // Ein Verkauf in diesem Geschäft
final double rabatt = 3. * prozent;
final double wert = 2 * tischwert + 1 * lampenwert;
final double rabattiert = wert *( 100. * prozent - rabatt );
final double brutto = rabattiert *( 100. * prozent + mwSt );
final double gerundet = Math.round( brutto * 100. )/ 100.;
final double forderung = gerundet / euro;

java.lang.System.out.println( "Zu zahlen sind " + forderung + " Euro." ); }

{ // Ein anderer Verkauf in diesem Geschäft
final double rabatt = 0. * prozent;
final double wert = 1 * lampenwert;
final double rabattiert = wert *( 100. * prozent - rabatt );
final double brutto = rabattiert *( 100. * prozent + mwSt );
final double gerundet = Math.round( brutto * 100. )/ 100.;
final double forderung = gerundet / euro;

java.lang.System.out.println( "Zu zahlen sind " + forderung + " Euro." ); }}}}}

Protokoll
Zu zahlen sind 1108.32 Euro.
Zu zahlen sind 168.2 Euro.

Das Geschäft ist ein Teil der Bundesrepublik Deutschland und die Bundesrepublik Deutschland ist ein Teil der Welt. Genauso sind auch die entsprechenden Blöcke in dem obigen Programm ineinander verschachtelt. Das ist nicht nur eine schöne Analogie, sondern hat auch den praktischen Nutzen, daß ein weiteres „Land“, das in dem Programm im äußeren Hauptblock angelegt wird, der die Welt repräsentiert, alle „Weltkonstanten“ von diesem Block übernimmt, aber eine eigene Mehrwertsteuer haben kann.

Dieses Prinzip wird anhand der beiden Verkäufe dargestellt: Da sie beide zum selben Geschäft gehören, „erben“ beide die Preisliste aus dem umgebenden Block, der das Geschäft repräsentiert. Jeder Verkauf hat jedoch seinen eigenen Warenwert, Rabatt und schließlich seine eigene Forderung.

Zitate *

JLS 10 6.3
The scope of a declaration is the region of the program within which the entity declared by the declaration can be referred to using a simple name, provided it is not shadowed (§6.4.1).
JLS 7 6.3 und JLS 10 6.3
The scope of a local variable declaration in a block (§14.4) is the rest of the block in which the declaration appears, starting with its own initializer  and including any further declarators to the right in the local variable declaration statement.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723812 stefan_ram:723812 Gültigkeitsbereiche in Java Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723812, slrprddef723812, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/gueltigkeitsbereich_java