ما هو المفضل Throwable للاستخدام في فئة فائدة منشئ ؟

StackOverflow https://stackoverflow.com/questions/398953

  •  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();
    }

    ...
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top