Komplexe Java-Anwendungen müssen oft auf Konstanten zugreifen. Dabei kann es vorkommen, dass viele Konstanten in mehreren Klassen zur Verfügung stehen müssen.
Möchte man in Java oft benötigte Konstanten in unterschiedlichen Klassen wiederverwenden, dann bieten sich hierfür die folgenden beiden Vorgehensweisen an:
- Alle Konstanten mit Hilfe eines Interfaces den Klassen zur Verfügung stellen oder
- Nur die benötigten Konstanten mittels import static in den Klassen verfügbar machen
Wir möchten in diesem Beitrag beide Vorgehensweisen vorstellen. Zur Info vorab: Der Ansatz, Konstanten mit Hilfe des import static Klassen gezielt zur Verfügung zu stellen, ist der bessere Programmierstil, wenngleich das Nutzen eines Interfaces auch eine, unter Java-Programmierern, sehr weit verbreitete Vorgehensweise ist.
Konstanten mit Hilfe eines Interfaces in Klassen verfügbar machen
Interfaces können in Java auch ohne Methoden definiert werden und somit nur aus Konstanten bestehen. Die Konstanten müssen als static final deklariert werden.
Da in einem Interface aber alle Konstanten implizit als public static final deklariert sind, müssen die Modifier nicht angegeben werden. Diese Aufgabe übernimmt dann der Java-Compiler.
Hinweis 1: Konstanten können in Klassen als static final und auch als final deklariert werden. In Interfaces sind Konstanten jedoch immer implizit als public static final deklariert, da von einem Interface selbst kein konkretes Objekt erstellt werden kann.
Hinweis 2: Methoden sind in Interfaces immer implizit als public abstract deklariert und müssen später von einer Klasse implementiert werden, um mit Hilfe eines Objekts konkret werden zu können. Zudem können Interface-Methoden nicht als static deklariert werden.
Wenn eine Klasse ein Interface implementiert, erbt sie alle Konstanten von dem Interface. Da ein Interface von mehr als einer Klasse implementiert werden kann, erhalten alle Klassen, die dieses Interface implementieren, die Konstanten des Interfaces.
Es ist daher üblich ein Interface zu definieren, das eine Sammlung von oft benötigten Konstanten darstellt. Alle Klassen, die auf diese Konstanten zugreifen müssen, können einfach dieses Interface implementieren und erhalten somit direkten Zugriff auf die Konstanten.
Auf die vom Interface geerbten Konstanten kann unqualifiziert zugegriffen werden. Als Zugriff kann anstelle des qualifizierten Zugriffs: Interfacename.Konstantenname
der unqualifizierte, direkte Zugriff: Konstantenname
verwendet werden.
Wir möchten nun eine kleine Java-Anwendung schreiben, die ein Interface als Konstantensammlung nutzt. Das Interface KonstantenUndDebug soll dazu nur aus Konstanten bestehen und auf Methoden verzichten.
Beispielanwendung: Die Testklasse für das Interface
/* * Beispielanwendung: die Testklasse für das Interface KonstantenUndDebug */ interface KonstantenUndDebug { // in einem Interface sind Konstanten immer implizit "public static final" // die Modifier müssen nicht angegeben werden // die unteren Konstanten sind alle "public static final" public static final int JAHR = 2014; public final int MONATE = 12; public static int TAGE = 365; public int STUNDEN = 8760; int MINUTEN = 525600; public static final boolean DEBUG = true; } public class KonstantenTest implements KonstantenUndDebug { public static void main (String[] args) { KonstantenTest myObj = new KonstantenTest(); System.out.println("\nWelches Jahr?: " + JAHR); System.out.println("Anzahl Monate: " + myObj.MONATE); System.out.println("Anzahl Tage: " + KonstantenUndDebug.TAGE); System.out.println("Anzahl Stunden: " + KonstantenTest.STUNDEN); System.out.println("Anzahl Minuten: " + MINUTEN); if (DEBUG) System.out.println("\nDebug Modus an."); } }
In dem oberen Quellcode wird neben den Interface-Konstanten JAHR, MONATE, TAGE, STUNDEN und MINUTEN auch die Konstante DEBUG definiert. Sie kann bspw. als Schalter für Debug-Ausgaben verwendet werden, ein weiteres Einsatzgebiet von Konstanten in Interfaces.
Die Konsolenausgabe der Beispielanwendung ist in der unteren Abbildung dargestellt:
Nachteile des Interface-Verfahrens
Die oben beschriebene Verwendungsart von Interfaces ist aber kein guter Programmierstil, obwohl sie von vielen Java-Entwicklern genutzt wird.
Das Verwenden eines Interfaces als Konstantensammlung bringt die folgenden Nachteile mit sich:
- Der Namensraum der Klasse wird mit read-only Variablen überschwemmt, die eventuell nicht genutzt werden.
- Wird keine Java-IDE verwendet, die automatisch auflöst woher die Konstanten kommen, kann es zeitaufwendig sein dies selbst manuell nachzuverfolgen.
- Ein Interface soll die Zugehörigkeit einer Klasse zu einem bestimmten Typ (dem des Interfaces) dokumentieren, was bei einem Konstanten-Interface keinen Sinn macht.
Aufgrund der oben genannten Nachteile, sollten Konstanten besser mit Hilfe der nachfolgenden Vorgehensweise in unterschiedlichen Klassen zur Verfügung gestellt werden.
Konstanten mit Hilfe von import static in Klassen verfügbar machen
Seit Java Version 5 können statische Elemente aus Klassen und Interfaces importiert werden und dadurch in der eigenen Klasse zur Verfügung gestellt werden. Diese Vorgehensweise wird als import static bezeichnet.
Einzelne statische Elemente können mit der import-Anweisung import static Klassenname.Elementname;
in die eigene Klasse importiert werden. Möchte man alle statischen Elemente einer Klasse oder eines Interfaces importieren, muss folgende import-Anweisung verwendet werden: import static Klassenname.*;
.
Das import static Verfahren kann sowohl bei Interfaces als auch bei Klassen angewendet werden. Dabei können als statische Elemente Methoden, Variablen und Konstanten importiert werden.
In der folgenden Beispielanwendung möchten wir nun mit Hilfe des import static Verfahrens die, für uns relevanten, statischen Elemente der Klasse Math in unserer eigenen Klasse ImportStaticTest verfügbar machen:
Beispielanwendung: Die Testklasse für das import static Verfahren
/* * Beispielanwendung: die Testklasse für das import static Verfahren */ // importiert nur die benötigten statischen Elemente der Klasse java-lang.Math import static java.lang.Math.E; import static java.lang.Math.PI; import static java.lang.Math.pow; // importiert alle statischen Elemente der Klasse java-lang.Math //import static java.lang.Math.*; public class ImportStaticTest { public static void main (String[] args) { System.out.println("\nKonstante pi: " + PI); System.out.println("Konstante e : " + E); System.out.println("\nErgebnis pi hoch e: " + pow(PI, E)); System.out.println("Ergebnis e hoch pi: " + pow(E, PI)); } }
In dem oberen Programm importieren wir drei statische Elemente aus der Klasse Math und machen sie dadurch in unserer eigenen Klasse direkt verfügbar. Das sind die beiden statischen Konstanten PI und E sowie die statische Methode pow(double a, double b).
Anschließend geben wir die beiden Werte der Konstanten auf der Kommandozeile aus. Dabei greifen wir direkt auf die Konstanten zu. Wir müssen keinen qualifizierten Zugriff (über den Klassennamen) verwenden, sondern können einfach den Namen der Konstante angeben.
Danach wird mit Hilfe der statischen Methode pow(double a, double b) das Ergebnis aus pie und epi berechnet und auf der Konsole ausgegeben.
Die Konsolenausgabe der Beispielanwendung ist in der unteren Abbildung dargestellt:
Vorteile von import static gegenüber einem Interface
Das import static Verfahren besitzt einige Vorteile gegenüber dem Verwenden eines Interfaces als Konstantensammlung:
- Der Namensraum der Klasse wird nicht mit read-only Variablen überschwemmt, da nur die benötigten Konstanten importiert werden.
- Da nur von den angegebenen Klassen und Interfaces importiert wird, kann leichter bestimmt werden, wo die Konstanten deklariert werden.
- Interfaces können jetzt ausschließlich dafür verwendet werden, wozu sie gedacht sind, nämlich die Zugehörigkeit einer Klasse zu einem bestimmten Typ (dem des Interfaces) zu dokumentieren und nicht Konstanten zur Verfügung zu stellen.
Zurück zum Programmierkurs für Java Einsteiger.
Comments 3
Danke. Ihr erklärt die Themen richtig gut und nachvollziehbar. Auch eure Beispielprogramme sind sehr hilfreich. Sie sind auf das Wesentliche reduziert und stellen oft Syntax-Varianten der themenbezogenen Befehle dar.
Bitte weiter so!
Author
Hallo Domme,
danke für die lobenden Worte!
Viele Grüße, Chris
Pingback: Interfaces (Schnittstellen) in Java