Ява: Статичний клас?


130

У мене клас, повний корисних функцій. Ігнорувати його екземпляр не має смислового сенсу, але я все ж хочу назвати його методи. Який найкращий спосіб впоратися з цим? Статичний клас? Анотація?


14
До речі, ви не можете зробити статику класу вищого рівня ...
Джон

Відповіді:


163

Приватний конструктор і статичні методи на класі, позначені як остаточні.


19
@matt b: Як зазначає Девід Роблз у своїй відповіді, вам не потрібно робити клас остаточним ... його не можна підкласирувати, оскільки підклас не зможе викликати конструктора суперкласу, оскільки він приватний. Однак ... не шкода бути явним. Але jfyi :-).
Том

93

Згідно чудової книги "Ефективна Java" :

Пункт 4: Застосування нестійкості за допомогою приватного конструктора

- Спроба закріпити неіснуючість шляхом створення конспекту класу не працює.

- Конструктор за замовчуванням генерується лише в тому випадку, якщо клас не містить явних конструкторів, тому клас можна зробити невідчутним, включивши приватний конструктор:

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

Оскільки явний конструктор приватний, він недоступний поза класом. AssertionError не є строго необхідним, але він забезпечує страхування на випадок випадкового виклику конструктора з класу. Це гарантує, що клас ніколи не буде інстанційним при будь-яких обставинах. Ця ідіома є м'яко контртуалітичною, оскільки конструктор надається чітко, щоб його не можна було викликати. Тому розумно включити коментар, як показано вище.

Як побічний ефект, ця ідіома також запобігає підкласу класу. Усі конструктори повинні викликати конструктор надкласового класу, явно або неявно, і підклас не матиме доступного конструктора надкласового класу, на який можна викликати.


1
Чому ви вибрали AssertionErrorнад іншої альтернативи , як IllegalStateException, UnsupportedOperationExceptionі т.д.?
Pacerier

@Pacerier Дивіться це .
bcsb1001

@ bcsb1001, це приводить нас до цього .
Пейсьєр

21

Схоже, у вас є клас корисності, схожий на java.lang.Math .
Підхід існує заключний клас з приватними конструкторськими та статичними методами.

Але будьте обережні, що це робить для перевірки, я рекомендую прочитати цю статтю
Статичні методи - це смерть для заповіту


Так це java.lang.Math "смерть до заповіту"?
Pacerier

1
Можливо, буде цікаво побачити, як він забиває під час пробігу code.google.com/p/testability-explorer
корона

6

Тільки щоб плавати вище за течією, статичні члени та класи не беруть участі в ОО і тому є злими. Ні, не зле, але серйозно, я б рекомендував для доступу звичайний клас з однотонним малюнком. Таким чином, якщо вам потрібно змінити поведінку в будь-яких випадках в дорозі, це не є основним переобладнанням. OO - ваш друг :-)

Мої $ 02


17
Однотонних теж вважають злими.
Дан Дайер

3
Ви використовуєте приватний конструктор, щоб запобігти інстанції або підкласифікації класу. Дивіться відповідь Девіда Роблеса: stackoverflow.com/questions/1844355/java-static-class/…
граб

5
сингл - не більше зла, ніж ін'єкція залежності :)
незаперечний

12
OO має своє місце, але бувають випадки, коли це просто не практично, або це буде марно витрачати ресурси - наприклад, щось таке просте, як Math.abs (). Немає причин створювати об'єкт лише для екземпляра об'єкта, коли статичний виклик методу послужив би вам так само добре, без жодних накладних витрат. ;)
пограбувати

2
@rob re OO, я згоден, Math.Abs, ймовірно, ніколи не потребує примірника. Коли я чую "у мене є клас корисності", я бачу Math.Avg (), де тепер потрібно додати підтримку для середньозваженого. Я бачу генератор Url, парам в, URL, який потребує відновлення для підтримки href, або лише URL-адреси тощо, і т.д. Крім того, зараз я відмовлюсь від стандартної оборонної тактики ОО, тестування! / мені качки
Беннетт Кріп

3

коментуйте аргументи "приватного конструктора": давай, розробники не такі дурні; але вони ледачі створюючи об'єкт, потім викликати статичні методи? не відбудеться

не витрачайте занадто багато часу, щоб переконатися, що ваш клас не можна зловживати. мати певну віру для своїх колег. і завжди є спосіб зловживати своїм класом незалежно від того, як ви його захищаєте. Єдине, чим не можна зловживати, - це річ, абсолютно марна.


7
Хтось, хто бачив (у виробничому коді, а не jsut код студента) object.staticMethod Я думаю, ви переоцінюєте здібності Joe Random Programmer! :-P
TofuBeer

2
  • Заключний клас та приватний конструктор (хороший, але не суттєвий)
  • Публічні статичні методи

1

Немає сенсу заявляти клас як static. Просто оголосіть його методи staticта зателефонуйте їм із імені класу як звичайні, як клас Math Java .

Крім того, хоча це не обов'язково робити конструктор приватним, це гарна ідея. Позначення конструктора приватним заважає іншим створювати екземпляри вашого класу, а потім викликати статичні методи з цих екземплярів. (Ці дзвінки працюють точно так само в Java, вони просто вводять в оману і шкодять читабельності вашого коду.)


1
Крім того, не забудьте зробити приватний конструктор.
Асаф

@Asaph: Погоджено. Я трохи додав це до своєї відповіді. Дякую.
Білл Ящірка

Якщо ви хочете статичних методів у внутрішньому класі, клас також повинен бути статичним.
Rui Marques

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.