سؤال

في ملف سياق تطبيق الربيع الخاص بي ، لدي شيء مثل:

<util:map id="someMap" map-class="java.util.HashMap" key-type="java.lang.String" value-type="java.lang.String">
    <entry key="some_key" value="some value" />
    <entry key="some_key_2" value="some value" />   
</util:map>

في فئة Java ، يشبه التنفيذ:

private Map<String, String> someMap = new HashMap<String, String>();
someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

في Eclipse ، أرى تحذيرًا يقول:

اكتب السلامة: ممثلون غير محددين من كائن إلى هاشماب

أي خطأ ارتكبت؟ كيف يمكنني حل المشكلة؟

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

المحلول

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

private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");

ثانياً ، يشكو المترجم HashMap دون التحقق مما إذا كان HashMap. ولكن ، حتى لو كنت ستفعل:

if(getApplicationContext().getBean("someMap") instanceof HashMap) {
    private Map<String, String> someMap = (HashMap<String, String>)getApplicationContext().getBean("someMap");
}

ربما لا تزال تحصل على هذا التحذير. المشكلة هي، getBean عائدات Object, ، لذلك من غير المعروف ما هو النوع. تحويله إلى HashMap لن يتسبب مباشرة في المشكلة في الحالة الثانية (وربما لن يكون هناك تحذير في الحالة الأولى ، لست متأكدًا من مدى تحطيم مترجم Java مع تحذيرات لـ Java 5). ومع ذلك ، فأنت تقوم بتحويله إلى HashMap<String, String>.

HashMaps هي حقًا خرائط تأخذ كائنًا كمفتاح ولديها كائن كقيمة ، HashMap<Object, Object> إن شئت. وبالتالي ، ليس هناك ما يضمن أنه عندما تحصل على الفول ، يمكن تمثيله كـ HashMap<String, String> لأنه يمكن أن يكون لديك HashMap<Date, Calendar> لأن التمثيل غير العام الذي يتم إرجاعه يمكن أن يكون له أي كائنات.

إذا كان الرمز يجمع ، ويمكنك التنفيذ String value = map.get("thisString"); بدون أي أخطاء ، لا تقلق بشأن هذا التحذير. ولكن إذا لم تكن الخريطة تمامًا من مفاتيح السلسلة لقيم السلسلة ، فستحصل على ملف ClassCastException في وقت التشغيل ، لأن الأدوية الجيرية لا يمكن أن تمنع هذا من حدوث هذه الحالة.

نصائح أخرى

المشكلة هي أن فريق العمل هو فحص وقت التشغيل - ولكن بسبب محو النوع ، في وقت التشغيل لا يوجد بالفعل فرق بين أ HashMap<String,String> و HashMap<Foo,Bar> لأي شخص آخر Foo و Bar.

يستخدم @SuppressWarnings("unchecked") وامسك أنفك. أوه ، وحملة للذهل الأولي في جافا :)

كما تشير الرسائل أعلاه ، لا يمكن التمييز بين القائمة بين أ List<Object> و List<String> أو List<Integer>.

لقد قمت بحل رسالة الخطأ هذه لمشكلة مماثلة:

List<String> strList = (List<String>) someFunction();
String s = strList.get(0);

كالآتي:

List<?> strList = (List<?>) someFunction();
String s = (String) strList.get(0);

Explanation: يتحقق تحويل النوع الأول من أن الكائن عبارة عن قائمة دون الاهتمام بالأنواع التي يتم الاحتفاظ بها داخل (نظرًا لأننا لا نستطيع التحقق من الأنواع الداخلية على مستوى القائمة). التحويل الثاني مطلوب الآن لأن المترجم يعرف فقط أن القائمة تحتوي على نوع من الكائنات. هذا يتحقق من نوع كل كائن في القائمة عند الوصول إليه.

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

في حالة الممثلين ، فإنه دائمًا ما يعطي تحذيرًا في هذه القضية. إذا كنت متأكدًا تمامًا من أن فريقًا معينًا سيكون آمنًا ، فيجب عليك التفكير في إضافة تعليق توضيحي مثل هذا (لست متأكدًا من بناء الجملة) قبل السطر مباشرة:

@SuppressWarnings (value="unchecked")

أنت تحصل على هذه الرسالة لأن GetBean يرجع مرجع كائن وأنت تقوم بإلقاءها على النوع الصحيح. Java 1.5 يمنحك تحذير. هذه هي طبيعة استخدام Java 1.5 أو أفضل مع الكود الذي يعمل مثل هذا. الربيع لديه نسخة الأنواع

someMap=getApplicationContext().getBean<HashMap<String, String>>("someMap");

على قائمة TODO.

إذا كنت ترغب حقًا في التخلص من التحذيرات ، فإن هناك شيء واحد يمكنك القيام به هو إنشاء فصل يمتد من الفصل العام.

على سبيل المثال ، إذا كنت تحاول استخدامها

private Map<String, String> someMap = new HashMap<String, String>();

يمكنك إنشاء فصل جديد مثل هذا

public class StringMap extends HashMap<String, String>()
{
    // Override constructors
}

ثم عندما تستخدم

someMap = (StringMap) getApplicationContext().getBean("someMap");

يعرف المترجم ما هي أنواع (لم تعد عامة) ، ولن يكون هناك تحذير. قد لا يكون هذا هو الحل الأمثل دائمًا ، فقد يجادل البعض في هذا النوع من الهزائم الغرض من الفصول العامة ، لكنك لا تزال تعيد استخدام كل الكود نفسه من الفئة العامة ، فأنت تعلن فقط في وقت الترجمة ما هو النوع تريد استخدامها.

حل آخر ، إذا وجدت نفسك يلقي نفس الكائن كثيرًا ولا تريد أن تتخلى عن الكود الخاص بك @SupressWarnings("unchecked"), ، سيكون لإنشاء طريقة مع التعليق التوضيحي. وبهذه الطريقة ، تقوم بتركيز الممثلين ، ونأمل أن تقلل من إمكانية الخطأ.

@SuppressWarnings("unchecked")
public static List<String> getFooStrings(Map<String, List<String>> ctx) {
    return (List<String>) ctx.get("foos");
}

يقل الرمز يسبب نوع تحذير السلامة

Map<String, Object> myInput = (Map<String, Object>) myRequest.get();

الحل البديل

قم بإنشاء كائن خريطة جديد دون ذكر المعلمات لأنه لم يتم التحقق من نوع الكائن المحتجز في القائمة.

الخطوة 1: إنشاء خريطة مؤقتة جديدة

Map<?, ?> tempMap = (Map<?, ?>) myRequest.get();

الخطوة 2: إنشاء الخريطة الرئيسية

Map<String, Object> myInput=new HashMap<>(myInputObj.size());

الخطوه 3: تكرار الخريطة المؤقتة وضبط القيم في الخريطة الرئيسية

 for(Map.Entry<?, ?> entry :myInputObj.entrySet()){
        myInput.put((String)entry.getKey(),entry.getValue()); 
    }

الحل لتجنب التحذير غير المحدد:

class MyMap extends HashMap<String, String> {};
someMap = (MyMap)getApplicationContext().getBean("someMap");
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top