Ответ 1
Существует утверждение: "Я утверждаю, что этот конструктор никогда не будет вызван". Итак, действительно, AssertionError
здесь верен.
Эффективное Java (второе издание), пункт 4, обсуждает использование частных конструкторов для обеспечения неинтересности. Вот пример кода из книги:
public final class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
Однако AssertionError
не похоже на то, что нужно бросить. Ничто не утверждается, так как API определяет использование AssertionError.
Существует ли в этой ситуации другой Throwable
? Обычно ли вы просто бросаете общий Exception
с сообщением? Или это типично для написания пользовательского Exception
для этого?
Это довольно тривиально, но больше всего на свете я предполагаю, что мне просто интересно это с точки зрения стиля и стандартов.
Существует утверждение: "Я утверждаю, что этот конструктор никогда не будет вызван". Итак, действительно, AssertionError
здесь верен.
Мне нравится включить комментарий Блоха:
// Suppress default constructor for noninstantiability
Или еще лучше поместить его в Error:
private UtilityClass()
{
throw new AssertionError("Suppress default constructor for noninstantiability");
}
UnsupportedOperationException звучит лучше всего, хотя проверенное исключение было бы еще лучше, поскольку оно могло бы предупредить кого-то, ошибочно создавшего экземпляр класса во время компиляции.
Как насчет IllegalAcessError?:)
Нет, нет, со всем уважением к Джошу Блоху, никогда не бросайте AssertionError
, если это не будет из утверждения. Если вы хотите здесь AssertionError, бросьте его с помощью assert(false)
. Затем кто-то, читающий код, может найти его позже.
Еще лучше, определите свое собственное исключение, скажем CantInstantiateUtilityClass
. то у вас будет код, который говорит
try {
// some stuff
} catch (CantInstantiateUtilityClass e) {
// react
}
чтобы читатель зрелище знал, что произошло.
Обновление
Каждый так часто какой-то проклятый дурак блуждает здесь и снова опускает это снова, почти через четыре года после этого факта. Итак, позвольте мне заметить, что стандарт по-прежнему определяет AssertionError
как результат неудачного утверждения, а не то, что, по мнению некоторых начинающих, должно быть выбрано вместо четко определенного информативного исключения. К сожалению, хорошая дисциплина исключений - это, пожалуй, наименее поощряемое умение в программировании на Java.
Когда код требует включения JUnit в качестве зависимости, например, в область теста maven <scope>test</scope>
, тогда переходите прямо к методу Assertion.fail()
и извлекайте выгоду из значительного улучшения ясности.
public final class UtilityClass {
private UtilityClass() {
fail("The UtilityClass methods should be accessed statically");
}
}
Вне области тестирования вы можете использовать что-то вроде следующего, что потребует статического импорта для использования, как описано выше. import static pkg.Error.fail;
public class Error {
private static final Logger LOG = LoggerFactory.getLogger(Error.class);
public static void fail(final String message) {
LOG.error(message);
throw new AssertionError(message);
// or use your preferred exception
// e.g InstantiationException
}
}
Какое следующее использование.
public class UtilityClassTwo {
private UtilityClassTwo() {
Error.fail("The UtilityClass methods should be accessed statically");
}
}
В самой идиоматической форме все они сводятся к следующему:
public class UtilityClassThree {
private UtilityClassThree() {
assert false : "The UtilityClass methods should be accessed statically";
}
}
Одно из встроенных исключений, UnsupportedOperationException, может быть выдано, чтобы указать, что "запрошенная операция не поддерживается".
private Constructor() {
throw new UnsupportedOperationException(
"Do not instantiate this class, use statically.");
}
Сломанное утверждение означает, что вы нарушили спецификацию контракта вашего кода. Так что это правильно.
Однако, поскольку я предполагаю, что вы будете частным образом создавать экземпляр экземпляра, он также вызовет конструктор и вызовет ошибку - если у вас нет другого конструктора?
Вы можете создать свой собственный класс, расширяющий Throwable
, например:
class NoninstantiabilityError extends Throwable
Это имеет следующие преимущества:
Throwable
маловероятно, что он будет случайно пойманThrowable
он проверяется, и случайный вызов соответствующего конструктора потребует перехвата исключения.Пример использования:
public final class UtilityClass {
private UtilityClass() throws NoninstantiabilityError {
throws new NoninstantiabilityError();
}
...
}