تحويل رمز Java Legacy إلى عام - كيفية استبدال الكائن بنوع؟

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

سؤال

// الكود القديم

void setCacheValue(String name, Object value){
    getServletContext().setAttribute(name, value);
}
Object getCacheValue(String name){
    return getServletContext().getAttribute(name);
}

// لذلك أريد استخدام عام لـ "نوع السلامة"

// first, set method seems working perfectly
<T> void setCacheObject(String name, T value){
    getServletContext().setAttribute(name, value);
}

// ثم ، هنا تأتي المشكلة

<T> T getCacheValue(String name){    
    // of course, I cannot change servlet class - it returns Object type
    Object value = getServletContext().getAttribute(name);
    // would this work:     
    return  (T) value;
    // this cast is meaningless... but how should I do it?
}

// هذا ما أقوم به في بلدي ينظف رمز الاتصال:

{
    double x = 1.2;
    setCacheValue("x", x);
    //...
    // later
    Double value = getCacheValue("x");
    // too bad cannot use primitive type - it cannot handle null

}

إذن ، ما هي الطريقة الصحيحة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

هذا غير ممكن بالفعل. ستحتاج إلى تمرير "الخرسانة" T بطريقة ما كوسيطة طريقة بحيث يكون النوع الفعلي معروفًا أثناء وقت التشغيل. النهج الشائع هو تمريره كـ Class<T>, ، بحيث يمكنك الاستفادة Class#cast():

<T> T getCacheValue(String name, Class<T> type) {
    return type.cast(getServletContext().getAttribute(name));
}

يمكنك استخدامه على النحو التالي:

Double value = getCacheValue("x", Double.class);

نصائح أخرى

تدعم MAP Generics نوعًا على جميع قيم الخريطة ، وليس نوعًا مختلفًا لقيم محددة. يمكنك أن ترى كيف تزييفه هنا. الفكرة هي في الأساس أن يكون لديك نوع الأمان على المفتاح ، حيث يحتوي المفتاح على نوع عام عليه والذي يربط ببساطة بالقيمة.

في نهاية اليوم ، لن تكون قادرًا على القيام بذلك بدون طاقم غير آمن ، ولكن يمكنك القيام بذلك بطريقة تجعل من غير المرجح للغاية أن تكون هناك مشكلة في طاقم ممثلين وبطريقة ما هي الأنواع إلى مستخدمو الفصل الخاص بك.

في الواقع هذا يجمع ، أيضا:

public class Test
{
    <T> T getCacheValue(String name){    
        // of course, I cannot change servlet class - it returns Object type
        Object value = getServletContext().getAttribute(name);
        // would this work:     
        return  (T) value;
        // this cast is meaningless... but how should I do it?
    }

    public static void main(String... args)
    {
        Test t = new Test();
        Double double = t.<Double>getCacheValue("Double");
    }
}

إنه نوع من الأهمية (ربما إذا أضفت typeCheck) لكنني وجدت أنه من المثير للاهتمام معرفة ذلك.

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