سؤال

كنت أتساءل ما هو نوع البيانات لمتغير القالب إذا تم تعيين الإرجاع إلى قالب. لقد رأيت هذا في كود في مكان ما، لكنني لا أعرف أين يلقي القيمة المستردة من الجلسة.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

الرمز لهذا الخارج هو:

MyClassType type = request.getFromSessionMap("abc");

يصادف الخط ClasscastException عند صب كائني. ولكن عندما أضيف إلى مشاهدة Session.getattribute ("ABC")، فإنه يدل على أن النوع هو myclasstype. سيكون موضع تقدير أي مساعدة.

على ما يبدو هذا الرمز الخاص لاستخدام القالب يجعل عودة GetFromSessionMap نوع متغير وبالتالي لا حاجة للمصرفة. يعمل هذا على جميع الحالات ولكن فجأة فشلت في جزء واحد من التعليمات البرمجية.

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

المحلول

على ما يبدو هذا الرمز الخاص لاستخدام القالب يجعل عودة GetFromSessionMap نوع متغير وبالتالي لا حاجة للمصرفة.

في الأساس هناك يجب أن يكون typecast في مكان ما بين الحصول على نتيجة session.getAttribute(sessionKey) والتخصيص ل MyClassType. وبعد لغة Java (و JVM) لن تسمح بعض الكائن الذي ليس MyClassType مثيل (أو نوع فرعي منه) ليتم تعيينه إلى MyClassType عامل.

بغض النظر عن كيفية كتابة التعليمات البرمجية، يجب أن يحدث Typecast. وبعد وبما أن السمة (على ما يبدو) ليست كذلك MyClassType (أو نوع فرعي)، أنت تحصل على ClassCastException.

لذلك السؤال الحقيقي هو السبب في عدم الحصول على خطأ في تجميع؟ والإجابة هي @SuppressWarnings("unchecked")في إذا قمت بإزالة هذا التحذير، فستحصل على رسالة خطأ "تحويل نوع غير آمن" لهذا السطر:

return (T) session.getAttribute(sessionKey);

في الحقيقة، لا يمكن ل Java القيام بأي نوع (حقيقي) يلقي إلى نوع عام. وهذا هو ما هي رسالة التحذير / الخطأ موجودة للإشارة إليها. في الواقع، بمجرد ترجمة الكود، هذا الرمز

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

في الواقع لا يختلف في المعنى من هذا:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

من الناحية الفنية، يطلق عليه هذا "محو النوع".

فأين يتم فحص النوع / typecast في الواقع؟ الجواب موجود في هذا الخط:

MyClassType type = request.getFromSessionMap("abc");

على الرغم من أنك لم تكتب Typecast هنا، فإن التعليمات البرمجية التي تم إنشاؤها بواسطة برنامج التحويل البرمجي Java يقوم بعمل Typecast قبل تعيين القيمة type. وبعد من المفترض ان. لأنه بقدر ما يعرف، فإن الحالة التي تعينها أي نوع الكائن.

اقترحت الملصقات الأخرى إضافة حجة فئة ل getFromSessionMap. وبعد في حد ذاته هذا يفعل لا شيء مطلقا. وبعد إذا قمت أيضا باستبدال الجسم من الطريقة مع:

return clazz.cast(session.getAttribute(sessionKey));

سوف تسبب الطريقة التي يجب القيام بها في الواقع فحص نوع حقيقي. ولكن هذا السبب الوحيد ClassCastException أن ألقيت في مكان مختلف. وبيان المهمة سوف لا تزال تفعل نوع من نوع مخفي!

نصائح أخرى

في مثال السؤال، نوع الإرجاع هو T. وبعد سيكون النوع المحسوس Object كما، ضمنيا، T extends Object. وبعد يتم إجراء المصبوب الفعلي في bytecode من طريقة الاتصال (يمكنك استخدامها javap -c لترى ذلك).

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

سيكون موضع تقدير أي مساعدة لأن شفتي يواجه كلاسكاستكساس.

إذا كنت تحصل على ClassCastException, ، هذا يعني أنك تحاول إلقاء شيء في شيء لا، كما هو الحال في التعليمات البرمجية التالية:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

ال ClassCastException يجب أن يكون لديك رسالة تفاصيل مستنيرة، مثل "java.lang.Ststring لا يمكن أن يلقي إلى java.util.date".

يمكنك استخدام النوع يلقي داخل هيئة الطريقة ("(ر) الدورة .getattribute (الدعارة)").

وهذا يعني أنك تقول صراحة للمترجم "أنا متأكد تماما من أن كائن عاد هو-ر وجاهز للتعامل مع الخطأ إذا لم يكن".

هنا كان افتراضك حول نوع السمة غير صحيح وحصلت على خطأ. لذلك، كل شيء صحيح ووقت التشغيل يوفر بالفعل نوع كائن السمات الحقيقي هذا ليس كذلك هو myclasstype.

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