370 Stimmen

Wie lassen sich Konstanten am besten in Java implementieren?

Ich habe solche Beispiele gesehen:

public class MaxSeconds {
   public static final int MAX_SECONDS = 25;
}

und nahm an, dass ich eine Klasse Constants haben könnte, um Konstanten darin zu verpacken und sie als static final zu deklarieren. Ich weiß praktisch kein Java überhaupt und frage mich, ob dies der beste Weg, um Konstanten zu erstellen ist.

2voto

davidxxx Punkte 114488

Wie lassen sich Konstanten am besten in Java implementieren?

Ein Ansatz, den wir wirklich vermeiden sollten : Verwendung von Schnittstellen zur Definition von Konstanten.

Eine Schnittstelle speziell für die Deklaration von Konstanten zu schaffen, ist wirklich das Schlimmste: Es macht den Grund zunichte, warum Schnittstellen entwickelt wurden: die Definition von Methodenkontrakten.

Selbst wenn eine Schnittstelle bereits existiert, um einen bestimmten Bedarf zu decken, macht es keinen Sinn, die Konstanten darin zu deklarieren, da Konstanten nicht Teil der API und des Vertrags sein sollten, der den Client-Klassen zur Verfügung gestellt wird.


Zur Vereinfachung haben wir im Großen und Ganzen 4 gültige Ansätze .

Mit static final String/Integer Feld :

  • 1) Verwendung einer Klasse, in der Konstanten deklariert sind, aber nicht nur.
  • 1 Variante) Erstellung einer Klasse, die nur Konstanten deklariert.

Mit Java 5 enum :

  • 2) Deklaration des Enums in einer verwandten Zweckklasse (also als verschachtelte Klasse).
  • 2 Variante) die Erstellung der Enum als eigenständige Klasse (also in einer eigenen Klassendatei definiert).

TLDR: Welches ist der beste Weg und wo befinden sich die Konstanten?

In den meisten Fällen ist die enum-Methode wahrscheinlich besser geeignet als die static final String/Integer Weg und ich persönlich denke, dass die static final String/Integer sollte nur verwendet werden, wenn es gute Gründe gibt, keine Enums zu verwenden.
Und darüber, wo wir die konstanten Werte deklarieren sollten, Die Idee besteht darin, zu suchen, ob es eine einzige existierende Klasse gibt, die eine spezifische und starke funktionale Kohäsion mit konstanten Werten besitzt. Wenn wir eine solche Klasse finden, sollten wir sie als Konstantenhalter verwenden . Andernfalls sollte die Konstante keiner bestimmten Klasse zugeordnet werden.


static final String / static final Integer gegen enum

Enums Verwendung ist wirklich ein Weg, um stark berücksichtigt.
Enums haben einen großen Vorteil gegenüber String o Integer konstantes Feld.
Sie legen einen stärkeren Kompilierungszwang fest. Wenn Sie eine Methode definieren, die die Aufzählung als Parameter nimmt, können Sie nur einen in der Aufzählungsklasse definierten Aufzählungswert (oder null) übergeben.
Bei String und Integer können Sie sie durch beliebige Werte eines kompatiblen Typs ersetzen, und die Kompilierung ist in Ordnung, auch wenn der Wert keine definierte Konstante in der static final String / static final Integer Felder.

Im Folgenden sind zum Beispiel zwei Konstanten in einer Klasse definiert als static final String Felder:

public class MyClass{

   public static final String ONE_CONSTANT = "value";
   public static final String ANOTHER_CONSTANT = "other value";
   . . .
}

Hier eine Methode, die eine dieser Konstanten als Parameter erwartet:

public void process(String constantExpected){
    ...    
}

Sie können es auf diese Weise aufrufen:

process(MyClass.ONE_CONSTANT);

ou

process(MyClass.ANOTHER_CONSTANT);

Aber keine Kompilierungsbeschränkung hindert Sie daran, sie auf diese Weise aufzurufen:

process("a not defined constant value");

Der Fehler tritt nur zur Laufzeit auf, und auch nur dann, wenn Sie zu einem bestimmten Zeitpunkt den übertragenen Wert überprüfen.

Bei enum sind keine Prüfungen erforderlich, da der Kunde nur einen enum-Wert in einem enum-Parameter übergeben kann.

Hier zum Beispiel zwei Werte, die in einer Enum-Klasse definiert sind (also von vornherein konstant sind):

public enum MyEnum {

    ONE_CONSTANT("value"), ANOTHER_CONSTANT(" another value");

    private String value;

    MyEnum(String value) {
       this.value = value;
    }
         ...
}

Hier eine Methode, die einen dieser Enum-Werte als Parameter erwartet:

public void process(MyEnum myEnum){
    ...    
}

Sie können es auf diese Weise aufrufen:

process(MyEnum.ONE_CONSTANT);

ou

process(MyEnum.ANOTHER_CONSTANT);

Aber die Zusammenstellung wird Ihnen niemals erlauben, sie auf diese Weise aufzurufen:

process("a not defined constant value");

Wo sollten wir die Konstanten deklarieren?

Wenn Ihre Anwendung eine einzige bestehende Klasse enthält, die einen spezifischen und starken funktionalen Zusammenhang mit den konstanten Werten besitzt, erscheinen 1) und 2) intuitiver.
Im Allgemeinen erleichtert es die Verwendung der Konstanten, wenn diese in der Hauptklasse deklariert werden, die sie bearbeitet oder die einen Namen hat, der sehr naheliegend ist, um zu erraten, dass wir sie darin finden werden.

In der JDK-Bibliothek werden beispielsweise die Exponential- und Pi-Konstantenwerte in einer Klasse deklariert, die nicht nur Konstantendeklarationen ( java.lang.Math ).

   public final class Math {
          ...
       public static final double E = 2.7182818284590452354;
       public static final double PI = 3.14159265358979323846;
         ...
   }

Die Kunden, die mathematische Funktionen verwenden, verlassen sich häufig auf die Math Klasse. So können sie Konstanten leicht finden und sich auch merken, wo E et PI sind auf sehr natürliche Weise definiert.

Wenn Ihre Anwendung keine bestehende Klasse enthält, die einen sehr spezifischen und starken funktionalen Zusammenhang mit den konstanten Werten hat, erscheinen die Varianten 1) und 2) intuitiver.
Im Allgemeinen erleichtert es die Verwendung der Konstanten nicht, wenn diese in einer Klasse deklariert werden, die sie manipuliert, während wir auch 3 oder 4 andere Klassen haben, die sie ebenso manipulieren, und keine dieser Klassen scheint natürlicher zu sein als andere, um konstante Werte zu hosten.
Hier ist es sinnvoll, eine eigene Klasse zu definieren, die nur konstante Werte enthält.
Zum Beispiel in der JDK-Bibliothek, die java.util.concurrent.TimeUnit enum wird nicht in einer bestimmten Klasse deklariert, da es nicht wirklich eine und nur eine JDK-spezifische Klasse gibt, die als die intuitivste erscheint, um sie zu enthalten:

public enum TimeUnit {
    NANOSECONDS {
      .....
    },
    MICROSECONDS {
      .....
    },
    MILLISECONDS {
      .....
    },
    SECONDS {
      .....
    },
      .....
}      

Viele Klassen, die in java.util.concurrent sie verwenden: BlockingQueue , ArrayBlockingQueue<E> , CompletableFuture , ExecutorService ... und eigentlich scheint keiner von ihnen besser geeignet zu sein, die Aufzählung zu enthalten.

1voto

Eine einzige, generische Konstantenklasse ist eine schlechte Idee. Konstanten sollten mit der Klasse gruppiert werden, mit der sie am logischsten verwandt sind.

Anstatt Variablen jeglicher Art (insbesondere enums) zu verwenden, würde ich vorschlagen, dass Sie Methoden verwenden. Erstellen Sie eine Methode mit demselben Namen wie die Variable und lassen Sie sie den Wert zurückgeben, den Sie der Variablen zugewiesen haben. Löschen Sie nun die Variable und ersetzen Sie alle Verweise auf sie durch Aufrufe der soeben erstellten Methode. Wenn Sie der Meinung sind, dass die Konstante so allgemein ist, dass Sie keine Instanz der Klasse erstellen müssen, nur um sie zu verwenden, dann machen Sie die konstante Methode zu einer Klassenmethode.

1voto

Tim Howland Punkte 7781

FWIW, eine Zeitüberschreitung in Sekunden Wert sollte wahrscheinlich eine Konfigurationseinstellung (lesen in aus einer Eigenschaftendatei oder durch Injektion wie in Spring) und nicht eine Konstante sein.

1voto

Ryan Delucchi Punkte 7568

Eine Konstante beliebigen Typs kann deklariert werden, indem eine unveränderliche Eigenschaft innerhalb einer Klasse erstellt wird (d. h. eine Member-Variable mit der final Modifikator). Typischerweise wird der static und public sind ebenfalls vorgesehen.

public class OfficePrinter {
    public static final String STATE = "Ready";  
}

Es gibt zahlreiche Anwendungen, bei denen der Wert einer Konstante eine Auswahl aus einem n-Tupel angibt (z. B. Aufzählung ) der Wahlmöglichkeiten. In unserem Beispiel können wir uns dafür entscheiden, einen Aufzählungstyp zu definieren, der die möglichen zugewiesenen Werte einschränkt (d. h. verbesserte Typensicherheit ):

public class OfficePrinter {
    public enum PrinterState { Ready, PCLoadLetter, OutOfToner, Offline };
    public static final PrinterState STATE = PrinterState.Ready;
}

1voto

chandrayya Punkte 11

Was ist der Unterschied?

1.

public interface MyGlobalConstants {
    public static final int TIMEOUT_IN_SECS = 25;
}

2.

public class MyGlobalConstants {
    private MyGlobalConstants () {} // Prevents instantiation
    public static final int TIMEOUT_IN_SECS = 25;
}

und mit MyGlobalConstants.TIMEOUT_IN_SECS wo immer wir diese Konstante benötigen. Ich denke, beides ist gleich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X