تحويل رمز Java Legacy إلى عام - كيفية استبدال الكائن بنوع؟
-
03-10-2019 - |
سؤال
// الكود القديم
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) لكنني وجدت أنه من المثير للاهتمام معرفة ذلك.