Konstanten und Gültigkeitsbereiche in Java [] (Konstanten und Gültigkeitsbereiche in Java), Lektion, Seite 723222
https://www.purl.org/stefan_ram/pub/gueltigkeitsbereiche_java (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Java-Kurs

Variablen und Gültigkeitsbereiche in Java 

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.

Die Variablendeklaration »final int zwoelf = 12;« bedeutet hier, 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.

Wir behandeln in dieser Lektion nur innerhalb eines Blocks  deklarierte Variablen, die wir auch manchmal Blockvariablen  nennen. Da der Gültigkeitsbereich einer solchen in einem Block deklarierten Variablen auf den relativ kleinen Bereich des Blockes eingeschränkt ist, wird solch eine Variable auch eine lokale Variable  genannt.

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.

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“.

Richtung einer Deklaration

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

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ java.lang.System.out.println( i ); final int i = 22; }}
Konsole
javac Main.java
Main.java:3: cannot resolve symbol
symbol : variable i
location: class Test
{ java.lang.System.out.println( i ); final int i = 22; }}
^

Wiederholung einer Deklaration

Nicht erlaubt ist es, in zwei Variablendeklarationen innerhalb eines Blocks den gleichen  Bezeichner zu verwenden, auch wenn die Bedeutung gleich sein soll.

Main.java
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 ); }}
Konsole
javac Main.java
Main.java:4: i is already defined in main(java.lang.String[])
final int i = 22; java.lang.System.out.println( i ); }}
^

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

Ende des Gültigkeitsbereichs

Der Gültigkeitsbereich (scope ) einer Block-Variablen endet mit dem Ende ihres Blocks. In der folgenden Übersetzungseinheit kann die Variable »k« also nach dem Ende ihres Blocks nicht mehr verwendet werden.

Main.java
public final class Main
{ public static void main( final java.lang.String[] args )
{ final int i = 22;
{ final int k = 22; } java.lang.System.out.println( k ); }}
Konsole
javac Main.java
Main.java:4: cannot resolve symbol (...)
{ final int k = 22; } java.lang.System.out.println( k ); }}
^

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 ); } }}
java.lang.System.out
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.

Verallgemeinerung Stilregel zum Gültigkeitsbereich

Der Wunsch Namenskollisionen zu vermeiden ist einer der wichtigsten Gründe für die folgende Stilregel.

Stilregel Der Gültigkeitsbereich eines Bezeichners sollte immer so klein wie möglich sein.

Der Name »i« ist sehr beliebt. Wenn der Gültigkeitsbereich dieses Namens in einem großen Programm nicht eingeschränkt werden würde, dann könnte dieser beliebte Name in dem Programm nur für eine Variable verwendet werden. Tatsächlich enthalten viele große Programme aber mehrere verschiedene Variablen mit dem Namen »i«, was dadurch ermöglicht wird, daß deren Gültigkeitsbereich jeweils eingeschränkt wird.

Verschachtelte Bereiche

Blöcke können ineinander verschachtelt werden, das heißt: ein Block kann einen anderen Block enthalten.

Der innere Block ist dann wieder 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.java
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 ); }}}
Konsole
javac Main.java
Main.java:4: i is already defined in main(java.lang.String[])
{ final int i = 23; java.lang.System.out.println( i ); }}}
^

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 = 6; java.lang.System.out.println( i ); } final int i = 9; 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 *

Ein Refaktor  ist eine Überarbeitung des Quelltextes eines Programmes, nach der sich das Programm weiterhin so verhält wie zuvor. Man kann also „von außen“ durch das Starten und Beobachten eines Programmes nicht erkennen, ob ein Refaktor angewendet wurde.

Setzen Sie die beiden Paare von Blockeinträgen, 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.)

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.printf( "Zu zahlen sind %.2f Euro.%n", forderung ); }

{ // 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.printf( "Zu zahlen sind %.2f Euro.%n", forderung ); }}}}}
transcript
Zu zahlen sind 1108.32 Euro.
Zu zahlen sind 168.20 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.

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 stefanram723222 stefan_ram:723222 Konstanten und Gültigkeitsbereiche in Java Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723222, slrprddef723222, 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/gueltigkeitsbereiche_java