ما هو المفضل Throwable للاستخدام في فئة فائدة منشئ ؟
-
29-08-2019 - |
سؤال
فعالة جافا (الطبعة الثانية), البند 4 من يناقش استخدام خاص منشئات لفرض noninstantiability.هنا هو رمز عينة من كتاب:
public final class UtilityClass {
private UtilityClass() {
throw new AssertionError();
}
}
ومع ذلك ، AssertionError
لا يبدو من الصواب أن رمي.لا شيء يجري "المزعومة" ، وهو كيف API يحدد استخدام AssertionError.
هل هناك مختلفة Throwable
هذا هو عادة في هذه الحالة ؟ لا أحد عادة مجرد رمي العامة Exception
مع رسالة ؟ أو هو شائع كتابة مخصص Exception
من أجل هذا ؟
انها تافهة جدا ، ولكن أكثر من أي شيء أعتقد أنني غريبة عن ذلك من أسلوب ومعايير المنظور.
المحلول
هناك تأكيد: "أنا أؤكد أن هذا المنشئ لن يسمى أبدا". لذلك، في الواقع، AssertionError
هو الصحيح هنا.
نصائح أخرى
أحب تشكيل تعليقات بلوش:
// Suppress default constructor for noninstantiability
أو أفضل بعد وضعه في الخطأ:
private UtilityClass()
{
throw new AssertionError("Suppress default constructor for noninstantiability");
}
غير المدعوم يبدو أصواتا كأفضل مناسبا، على الرغم من أن استثناء محدد سيكون أفضل، لأنه قد يحذر شخصا مثلايا على الفئة في وقت الترجمة.
ماذا عن غير شرعيالكرور ? :)
لا لا لا، مع كل الاحترام الواجب لجوش بلوخ، لا ترمي أبدا AssertionError
ما لم يكن من تأكيد. إذا كنت تريد AssertionError هنا، رميها assert(false)
. وبعد ثم شخص يقرأ الرمز يمكن أن يجدها لاحقا.
أفضل، وحدد استثناءك الخاص، قل CantInstantiateUtilityClass
. وبعد ثم سيكون لديك رمز يقول
try {
// some stuff
} catch (CantInstantiateUtilityClass e) {
// react
}
بحيث يعرف قارئ الماسك ماذا او ما حدث.
تحديث
كل ما في كثير من الأحيان يخدع البعض اللعنة من هنا وهبوطا هذا مرة أخرى، بعد أربع سنوات تقريبا بعد الحقيقة. لذلك، اسمحوا لي أن ألاحظ أن المعيار ما يزال يحدد AssertionError
نتيجة للتأكيد الفاشل، وليس كما يفكر بعض المبتدئين ينبغي ليتم إلقاؤها بدلا من استثناء مفيد محدد جيدا. للأسف، فإن الانضباط الاستثناء الجيد ربما أقل مهارة شجع في برمجة Java.
عندما يتطلب القانون إدراج JUnit كما تبعية مثل داخل مخضرم نطاق الاختبار <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 {
throw new NoninstantiabilityError();
}
...
}