سؤال

عادةً ما يقوم المترجم بإنشاء تعليمات برمجية لأداء الملاكمة وإلغاء التغليف.ولكن ماذا يفعل المترجم إذا لم تكن هناك حاجة إلى القيم المعبأة؟هل المترجم (Oracle Standard) ذكي بما يكفي لتحسينه؟

ألق نظرة على هذه الطريقة:

public static void requireInRange(int index, Object[] array) {
    if(index < 0 || index >= array.length)
        throw new IndexOutOfBoundsException();
}

المعلومات الوحيدة ذات الصلة هي array.length, ، لذلك سيكون من غير المجدي وضع كل قيمة في المصفوفة على سبيل المثال.كما في هذا الكود:

int[] anArray = {3, 4, 2};
requireInRange(3, anArray);

هل سيقوم المترجم بالفعل بإدخال التعليمات البرمجية لملاكمة كل قيمة من المصفوفة؟

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

المحلول

لا يوجد autoboxing في التعليمات البرمجية الخاصة بك.في الحقيقة نظرا:

public static void requireInRange(int index, Object[] array) {
   ...
}

int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!

في حين أن int يمكن أن يكون autoboxed إلى Integer, ، ان int[] يفعل لا الحصول على علبة تلقائية ل Integer[] بواسطة جافا.يمكنك كتابة وظائف المكتبة للقيام بذلك، ولكن اللغة لن تسهل هذا التحويل.

وهذا في الواقع مصدر الكثير من الالتباس فيما يتعلق على سبيل المثال. Arrays.asList(anIntArray) يجري "مكسور"، لأنه بدلاً من إرجاع أ List<Integer>, فإن ما يتم إرجاعه هو في الواقع عنصر واحد List<int[]>.


ولكن ماذا عن الأداء؟؟؟

إقتباس من دليل لغة جافا/Autoboxing:

ليس من المناسب استخدام autoboxing وunboxing للحوسبة العلمية، أو غيرها من التعليمات البرمجية الرقمية الحساسة للأداء.ان Integer ليس بديلا عن int;يؤدي التخصيص التلقائي والإلغاء التلقائي إلى طمس التمييز بين الأنواع البدائية والأنواع المرجعية، لكنهما لا يلغيانه.

باختصار، عندما يحدث التشغيل التلقائي، فإن الأداء يأخذ بالتأكيد بعض النجاح.هناك أشياء معينة تساعد على التخفيف من هذا الأمر، على سبيل المثال.آلية التخزين المؤقت المضمنة في هذه الأنواع.ولهذا السبب تحصل على ما يلي:

    System.out.println(
        ((Integer) 0) == ((Integer) 0)
    );
    // true

    System.out.println(
        ((Integer) 10000) == ((Integer) 10000)
    );
    // false (implementation-specific)

ما حدث هنا هو أنه عندما 0 يكون تلقائيا محاصر، لا جديد Integer تم إنشاء المثيل بالفعل:القيم في نطاق معين هو مخبأة لأغراض التشغيل الآلي، للمساعدة في الأداء. 10000 في معظم التطبيقات ربما يقع خارج هذا النطاق، ولكن بعض تطبيقات JVM تسمح لك بتحديد نطاق ذاكرة التخزين المؤقت إذا لزم الأمر.


لكني أريد فقط الحصول على طول المصفوفة !!!

هناك العديد من الطرق لتسهيل عملك requireInRange للعمل مع أي نوع من المصفوفات.لسوء الحظ، فإن العمل مع مجموعة من العناصر الأولية في Java يعني في كثير من الأحيان الكثير من التكرار.وهذا يعني توفير الأحمال الزائدة ل int[], boolean[], byte[], Object[], الخ على حدة.

الخيار الأكثر إيجازًا هو استخدام الانعكاس، لكن هذا له إيجابيات وسلبيات.بشكل عام، لا ينبغي أن يكون التفكير هو الحل المفضل لمعظم السيناريوهات.

وقد قلت ذلك، java.lang.reflect.Array لديه int getLength(Object array) static الطريقة التي يمكن أن ترجع طول أي مجموعة مصفوفة.إنها ليست آمنة للكتابة (مثل معظم آليات الانعكاس)؛تمرير تجميعات غير صفيف، ولكن يلقي IllegalArgumentException في وقت التشغيل.

أسئلة ذات صلة

نصائح أخرى

هل سيقوم برنامج التحويل البرمجي فعليًا بإدراج رمز الملاكمة لكل قيمة من الصفيف؟

سيرفض المترجم الرمز لأن int[] لا يمكن نقلها إلى طريقة تأخذ Object[] معامل.

يحدث Autoboxing فقط للقيم البدائية الفردية ، أبدًا للمصفوفات بأكملها.

إذا كنت في شك ، يمكنك افتراض أن المترجم لا يحسن الرمز. بشكل عام ، يقوم بترجمة حرفية للرمز.

بالإضافة إلى ذلك ، إذا افترضت أن JVM تقوم بعمل جيد للغاية في تحسين الكود في وقت التشغيل. لن أفترض أن هذا يحدث أي فرق ما لم يكن لديك سبب وجيه (مثل Pforler) للاشتباه في أنها مشكلة.

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