لماذا لا يستطيع مترجم/JVM فقط جعل autoboxing "فقط العمل" ؟

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

سؤال

Autoboxing هو مخيفة إلى حد ما.بينما أنا أفهم تماما الفرق بين == و .equals لا أستطيع إلا أن تساعد لديك اتبع علة الجحيم لي:

    final List<Integer> foo = Arrays.asList(1, 1000);
    final List<Integer> bar = Arrays.asList(1, 1000);
    System.out.println(foo.get(0) == bar.get(0));
    System.out.println(foo.get(1) == bar.get(1));

أن يطبع

true
false

لماذا لم تفعل ذلك بهذه الطريقة ؟ ذلك أن تفعل شيئا مع مؤقتا الاعداد الصحيحه ، ولكن إذا كان هذا هو الحال لماذا لا مجرد ذاكرة التخزين المؤقت جميع الأعداد المستخدمة من قبل البرنامج ؟ أو لماذا لا JVM دائما السيارات خدمة unbox إلى بدائية ؟

الطباعة false false أو true صحيحا لكان أفضل.

تحرير

أنا أختلف عن الكسر من القانون القديم.من خلال وجود foo.get(0) == bar.get(0) العودة الحقيقية لقد كسرت الشفرة.

لا يمكن أن يكون هذا حل في المترجم المستوى من خلال استبدال عدد صحيح مع الباحث في رمز بايت (طالما أنها لم يكلف null)

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

المحلول

  • لماذا فعلوا ذلك بهذه الطريقة؟

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

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

لا يمكن تخزين جميع الأعداد الصحيحة مؤقتًا ، لأن الآثار المترتبة على الذاكرة ستكون هائلة.

  • لماذا لا JVM دائما unbox إلى بدائية؟

لأن JVM لا يمكن أن تعرف ما تريد. أيضا ، يمكن أن يكسر هذا التغيير بسهولة الكود القديم غير مصمم للتعامل مع هذه الحالة.

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

بدلاً من ذلك ، قلقًا جدًا بشأن هذا ، فقط تذكر هذه القاعدة بدلاً من ذلك:

مطلقا قارن الكائنات بـ == إلا إذا كنت تنوي مقارنتها من خلال مراجعها. إذا قمت بذلك ، فلا يمكنني التفكير في سيناريو تصادف فيه مشكلة.

نصائح أخرى

هل يمكنك أن تتخيل مدى سوء الأداء إذا كان كل شيء Integer تحمل النفقات العامة للاعتقال؟ أيضا لا يعمل ل new Integer.

لا يمكن دائمًا أن تكون لغة Java (وليس مشكلة JVM) تلقائيًا لأن الكود المصمم لـ Java قبل 1.5 يجب أن يعمل.

Integers في نطاق البايت هي نفس الكائن ، لأنهم مؤقتا. Integers خارج نطاق البايت لا.إن جميع الأعداد الصحيحة أن يكون مؤقتا ، تخيل الذاكرة المطلوبة.

و من هنا

النتيجة من كل هذا السحر هو أنه يمكنك أن تتجاهل إلى حد كبير التمييز بين الباحث و صحيح ، مع بعض المحاذير.صحيح التعبير يمكن أن يكون لها قيمة فارغة.إذا كان البرنامج يحاول autounbox null, فإنه سيتم رمي NullPointerException.عامل التشغيل == ينفذ مرجعية الهوية مقارنات على عدد صحيح تعابير قيمة المساواة مقارنات على الباحث التعبيرات.وأخيرا ، هناك أداء التكاليف المرتبطة الملاكمة و علبته ، حتى لو كان ذلك تلقائيا

إذا تخطيت Autoboxing تمامًا ، فلا يزال لديك هذا السلوك.

final List<Integer> foo =
  Arrays.asList(Integer.valueOf( 1 ), Integer.valueOf( 1000 ));
final List<Integer> bar =
  Arrays.asList(Integer.valueOf( 1 ), Integer.valueOf( 1000 ));

System.out.println(foo.get(0) == bar.get(0)); // true
System.out.println(foo.get(1) == bar.get(1)); // false

كن أكثر وضوحًا إذا كنت تريد سلوكًا محددًا:

final List<Integer> foo =
  Arrays.asList( new Integer( 1 ), new Integer( 1000 ));
final List<Integer> bar =
  Arrays.asList( new Integer( 1 ), new Integer( 1000 ));

System.out.println(foo.get(0) == bar.get(0)); // false
System.out.println(foo.get(1) == bar.get(1)); // false

هذا هو السبب ، لماذا يمتلك Eclipse Autoboxing كتحذير افتراضيًا.

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

في برمجة جافا المحترفين, فقط بوصات أدناه كانت الكاتب يتحدث عن المشكلات المتعلقة باستخدام الأعداد الصحيحة ذات الصناديق التلقائية كمفتاح في الهوية HashMap ، ويستخدم مفاتيح عدد صحيح من الصناديق في نقطة الضعيفة. القيم المثال التي يستخدمها أكبر من 128 ، لذلك تنجح مكالمة مجموعة القمامة الخاصة به. إذا كان شخص ما يستخدم مثاله واستخدام القيم الأصغر من 128 ، فإن مثاله سيفشل (بسبب المفتاح الذي يتم حصوله على Perma).

عندما تكتب

foo.get(0)

المترجم لا يهم كيفية إنشاء القائمة. ينظر فقط إلى نوع وقت الترجمة من القائمة FOO. لذلك ، إذا كانت هذه قائمةu003CInteger> ، سوف يعامل ذلك كقائمةu003CInteger> ، كما من المفترض أن تفعل ، وقائمةu003CInteger> الحصول على () دائما يعيد عدد صحيح. إذا كنت تريد استخدام == ، فعليك الكتابة

System.out.println(foo.get(0).intValue() == bar.get(0).intValue());

ليس

System.out.println(foo.get(0) == bar.get(0));

لأن هذا له معنى مختلف تماما.

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