Załóżmy, że musisz zdefiniować klasę, w której wszystko co robi, to przechowywanie stałych.
public static final String SOME_CONST = "SOME_VALUE";
Jaki jest preferowany sposób zrobienia tego?
- Berło
- Klasa abstrakcyjna
- Klasa końcowa
Którego powinienem użyć i dlaczego?
Wyjaśnienia do niektórych odpowiedzi:
Wyliczenia - nie zamierzam używać wyliczeń, niczego nie wyliczam, zbieram tylko stałe, które nie są ze sobą w żaden sposób powiązane.
Interfejs - nie zamierzam ustawiać żadnej klasy jako implementującej interfejs. Po prostu chcesz użyć interfejsu zadzwonić stałe tak: ISomeInterface.SOME_CONST
.
java
class-constants
Yuval Adam
źródło
źródło
Odpowiedzi:
Użyj ostatniej klasy. dla uproszczenia możesz następnie użyć importu statycznego, aby ponownie użyć wartości w innej klasie
public final class MyValues { public static final String VALUE1 = "foo"; public static final String VALUE2 = "bar"; }
w innej klasie:
import static MyValues.* //... if(variable.equals(VALUE1)){ //... }
źródło
VALUE1.equals(variable)
użyłbym go, ponieważ pozwala uniknąć NPE.Twoje wyjaśnienie brzmi: „Nie będę używał wyliczeń, niczego nie wyliczam, po prostu zbieram pewne stałe, które nie są ze sobą w żaden sposób powiązane”.
Jeśli stałe w ogóle nie są ze sobą powiązane, dlaczego chcesz je zebrać razem? Umieść każdą stałą w klasie, z którą jest najbliżej spokrewniona.
źródło
Moje sugestie (malejąco według preferencji):
1) Nie rób tego . Utwórz stałe w aktualnej klasie, w której są najbardziej odpowiednie. Posiadanie klasy / interfejsu typu „worek stałych” nie jest zgodne z najlepszymi praktykami obiektowymi.
Ja i wszyscy inni od czasu do czasu ignorujemy # 1. Jeśli masz zamiar to zrobić, to:
2) Klasa końcowa z prywatnym konstruktorem Zapobiegnie to przynajmniej nadużywaniu twojego „worka stałych” poprzez rozszerzenie / zaimplementowanie go w celu uzyskania łatwego dostępu do stałych. (Wiem, że powiedziałeś, że tego nie zrobisz - ale to nie znaczy, że ktoś przyjdzie po Tobie)
3) Interfejs To zadziała, ale nie moje preferencje, podając ewentualne nadużycie w punkcie 2.
Ogólnie rzecz biorąc, to, że są to stałe, nie oznacza, że nie powinieneś nadal stosować do nich normalnych zasad oo. Jeśli nikomu poza jedną klasą zależy na stałej - powinna być prywatna i należąca do tej klasy. Jeśli tylko testy dotyczą stałej - powinna znajdować się w klasie testowej, a nie w kodzie produkcyjnym. Jeśli stała jest zdefiniowana w wielu miejscach (nie tylko przypadkowo ta sama) - refaktoryzuj, aby wyeliminować powielanie. I tak dalej - traktuj je jak metodę.
źródło
Jak zauważa Joshua Bloch w Effective Java:
Możesz użyć Enum, jeśli wszystkie twoje stałe są powiązane (jak nazwy planet), umieścić stałe wartości w klasach, z którymi są powiązane (jeśli masz do nich dostęp), lub użyć nieinstanowalnej klasy narzędziowej (zdefiniuj prywatny domyślny konstruktor) .
class SomeConstants { // Prevents instanciation of myself and my subclasses private SomeConstants() {} public final static String TOTO = "toto"; public final static Integer TEN = 10; //... }
Następnie, jak już wspomniano, możesz użyć importu statycznego, aby użyć stałych.
źródło
Moją preferowaną metodą jest w ogóle tego nie robić. Wiek stałych prawie umarł, gdy Java 5 wprowadziła wyliczenia bezpieczne dla typów. Jeszcze wcześniej Josh Bloch opublikował (nieco bardziej rozwlekłą) wersję tego, która działała na Javie 1.4 (i wcześniejszych).
O ile nie potrzebujesz współdziałania z jakimś starszym kodem, naprawdę nie ma już powodu, aby używać nazwanych stałych typu String / integer.
źródło
Po prostu użyj ostatniej klasy.
Jeśli chcesz mieć możliwość dodawania innych wartości, użyj klasy abstrakcyjnej.
Używanie interfejsu nie ma większego sensu, interfejs ma określać kontrakt. Chcesz tylko zadeklarować pewne wartości stałe.
źródło
Czy wyliczenia nie są najlepszym wyborem do tego typu rzeczy?
źródło
enum
są w porządku. IIRC, jedna pozycja w efektywnej Javie (wyd. 2), maenum
stałe wyliczające standardowe opcje implementujące [słowo kluczowe Java]interface
dla dowolnej wartości.Preferuję użycie [słowa kluczowego Java] zamiast
interface
afinal class
dla stałych. Niejawnie otrzymujeszpublic static final
. Niektórzy ludzie będą argumentować, że aninterface
pozwala złym programistom na zaimplementowanie go, ale źli programiści będą pisać kod, który jest do niczego, bez względu na to, co robisz.Który wygląda lepiej?
public final class SomeStuff { private SomeStuff() { throw new Error(); } public static final String SOME_CONST = "Some value or another, I don't know."; }
Lub:
public interface SomeStuff { String SOME_CONST = "Some value or another, I don't know."; }
źródło
Lub 4. Umieść je w klasie, która zawiera logikę używającą najczęściej stałych
... przepraszam, nie mogłem się oprzeć ;-)
źródło
Jedną z wad prywatnego konstruktora jest to, że metoda nigdy nie mogła zostać przetestowana.
Wyliczenie według koncepcji natury, które jest dobre do zastosowania w określonym typie domeny, zastosowanie go do zdecentralizowanych stałych nie wygląda wystarczająco dobrze
Pojęcie wyliczenia to „Wyliczenia to zbiory ściśle powiązanych elementów”.
Rozszerzanie / implementowanie stałego interfejsu jest złą praktyką, trudno jest pomyśleć o wymaganiu rozszerzenia niezmiennej stałej zamiast odwoływania się do niej bezpośrednio.
Jeśli zastosujesz narzędzie wysokiej jakości, takie jak SonarSource, istnieją zasady, które zmuszają programistę do porzucenia stałego interfejsu, jest to niezręczna rzecz, ponieważ wiele projektów korzysta ze stałego interfejsu i rzadko zdarza się, aby rzeczy "rozszerzające" miały miejsce na stałych interfejsach
źródło