Java: klasa statyczna?


131

Mam klasę pełną funkcji użytkowych. Tworzenie instancji tego nie ma sensu semantycznego, ale nadal chcę wywoływać jego metody. Jak najlepiej sobie z tym poradzić? Klasa statyczna? Abstrakcyjny?


14
Nawiasem mówiąc, nie możesz zrobić statycznej klasy na najwyższym poziomie ...
Jon

Odpowiedzi:


164

Prywatny konstruktor i metody statyczne w klasie oznaczonej jako ostateczna.


19
@matt b: Jak zauważył David Robles w swojej odpowiedzi, nie ma potrzeby, aby klasa była ostateczna ... nie można jej dodać do podklasy, ponieważ podklasa nie będzie mogła wywołać konstruktora superklasy, ponieważ jest ona prywatna. Jednak ... nie ma nic złego w wyrażaniu się wprost. Ale jfyi :-).
Tom

93

Według wielkiej książki „Effective Java” :

Punkt 4: Wymuszaj nieinstanowalność za pomocą prywatnego konstruktora

- Próba wymuszenia nieinstancji poprzez tworzenie abstrakcji klasy nie działa.

- Domyślny konstruktor jest generowany tylko wtedy, gdy klasa nie zawiera jawnych konstruktorów, więc klasę można uczynić nieinstanowalną, dołączając konstruktor prywatny:

// Noninstantiable utility class
public class UtilityClass
{
    // Suppress default constructor for noninstantiability
    private UtilityClass() {
        throw new AssertionError();
    }
}

Ponieważ jawny konstruktor jest prywatny, jest niedostępny poza klasą. AssertionError nie jest ściśle wymagane, ale zapewnia ubezpieczenie na wypadek, gdyby konstruktor został przypadkowo wywołany z poziomu klasy. Gwarantuje, że klasa nigdy nie zostanie utworzona w żadnych okolicznościach. Ten idiom jest nieco sprzeczny z intuicją, ponieważ konstruktor jest dostarczony wyraźnie, więc nie można go wywołać. Dlatego rozsądnie jest zamieścić komentarz, jak pokazano powyżej.

Jako efekt uboczny ten idiom zapobiega również podklasie klasy. Wszystkie konstruktory muszą wywoływać konstruktor nadklasy, jawnie lub niejawnie, a podklasa nie miałaby dostępnego konstruktora nadklasy do wywołania.


1
Dlaczego wybraliście AssertionErrorna inne alternatywy, takie jak IllegalStateException, UnsupportedOperationExceptionitp?
Pacerier,

@Pacerier Zobacz to .
bcsb1001

@ bcsb1001, To prowadzi nas do tego .
Pacerier


6

Aby płynąć pod prąd, statyczni członkowie i klasy nie uczestniczą w OO i dlatego są źli. Nie, nie jest zły, ale poważnie, poleciłbym zwykłą klasę z pojedynczym wzorcem dostępu. W ten sposób, jeśli musisz zmienić zachowanie w jakimkolwiek przypadku na drodze, nie jest to poważna zmiana narzędzi. OO jest twoim przyjacielem :-)

Moje .02


18
Singletony też są uważane za złe.
Dan Dyer

3
Używasz konstruktora prywatnego, aby uniemożliwić komukolwiek tworzenie instancji lub tworzenie podklas klasy. Zobacz odpowiedź Davida Roblesa: stackoverflow.com/questions/1844355/java-static-class/ ...
okradł

5
singleton nie jest bardziej zły niż zastrzyk zależności :)
bezapelacyjny

12
OO ma swoje miejsce, ale są chwile, kiedy jest po prostu niepraktyczne lub byłoby to marnotrawstwem zasobów - na przykład coś tak prostego jak Math.abs (). Nie ma powodu, aby tworzyć instancję obiektu tylko po to, by utworzyć instancję obiektu, podczas gdy statyczne wywołanie metody równie dobrze by Ci służyło bez żadnego z OO-narzutów. ;)
obrabuj

2
@rob re OO, zgadzam się, Math.Abs ​​prawdopodobnie nigdy nie potrzebuje instancji. Kiedy słyszę „Mam klasę użytkową”, widzę Math.Avg (), gdzie należy teraz dodać obsługiwane dla średniej ważonej. Widzę generator adresu URL, parametr wejściowy, wyjściowy adresu URL, który należy refaktoryzować, aby obsługiwał href, lub tylko adres URL itp. Z tego powodu posiadanie klasy narzędziowej opartej na obiektach obiektowych może się opłacić. Teraz zrezygnuję ze standardowej taktyki obronnej OO, testując! / me ducks
Bennett Dill,

3

skomentuj argumenty „prywatnego konstruktora”: daj spokój, programiści nie są tacy głupi; ale są leniwi. tworzenie obiektu, a następnie wywołanie metod statycznych? nie wydarzy się.

nie trać zbyt wiele czasu, aby upewnić się, że Twoja klasa nie zostanie niewłaściwie wykorzystana. miej wiarę w swoich kolegów. i zawsze istnieje sposób na niewłaściwe wykorzystanie Twojej klasy, bez względu na to, jak ją chronisz. jedyną rzeczą, której nie można nadużyć, jest rzecz całkowicie bezużyteczna.


7
Ktoś, kto widział (w kodzie produkcyjnym, a nie w kodzie studenta jsut) object.staticMethod Myślę, że przeceniasz możliwości Joe Random Programmer! :-P
TofuBeer

2
  • Klasa końcowa i prywatny konstruktor (dobry, ale nie niezbędny)
  • Publiczne metody statyczne

1

Nie ma sensu deklarować klasy jako static. Po prostu zadeklaruj jego metody statici wywołaj je z nazwy klasy w normalny sposób, jak klasa Math w Javie .

Ponadto, mimo że nie jest absolutnie konieczne, aby konstruktor był prywatny, warto to zrobić. Oznaczenie konstruktora jako prywatnego uniemożliwia innym osobom tworzenie wystąpień Twojej klasy, a następnie wywoływanie metod statycznych z tych wystąpień. (Te wywołania działają dokładnie tak samo w Javie, po prostu wprowadzają w błąd i szkodzą czytelności kodu).


1
Nie zapomnij też stworzyć prywatnego konstruktora.
Asaph

@ Asaph: Zgoda. Dodałem trochę do mojej odpowiedzi. Dzięki.
Bill the Lizard

Jeśli chcesz, aby metody statyczne znajdowały się w klasie wewnętrznej, klasa musi również być statyczna.
Rui Marques

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.