[Java] هل يمكن ل جفم غ تحريك الأجسام في منتصف المقارنة المرجعية، مما يؤدي إلى فشل الفشل حتى عندما يشير كلا الجانبين إلى نفس الكائن؟


Answers

مصدر:

https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.21.3

الجواب القصير هو النظر في مواصفات جافا 8: لا.

سوف المشغل == دائما إجراء فحص المساواة الكائن (بالنظر إلى أن لا إشارة لاغية). حتى إذا تم نقل الكائن، الكائن لا يزال نفس الكائن .

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

يمكن بالطبع أن يكون بعض التنفيذ الغامض ل جفم لا يفرض هذا لأي سبب غريب للأداء. وإذا كان الأمر كذلك، سيكون من الحكمة أن نتحرك ببساطة من تلك الآلية المشتركة ...

Question

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

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

أي، هل هناك أي حالة لا تطبع فيها الشفرة التالية "صحيح"؟

Foo foo = new Foo();
Foo bar = foo;
if(foo == bar) {
    System.out.println("true");
}

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




غس يحدث فقط في نقاط في البرنامج حيث يتم تعريف الدولة بشكل جيد و جفم لديه معرفة دقيقة حيث كل شيء في سجلات / كومة / على كومة بحيث يمكن إصلاح جميع المراجع حتى عندما يحصل على نقل كائن.

أي أنها لا يمكن أن تحدث بين تنفيذ تعليمات التجميع التعسفي. من الناحية المفاهيمية يمكنك التفكير في حدوثها بين تعليمات بيتكود من جفم مع غ ضبط جميع المراجع التي تم إنشاؤها بواسطة تعليمات السابقة.




كائن جافا عقد مرجع إلى "كائن" لا إلى مساحة الذاكرة حيث يتم تخزين الكائن.

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

كمثال للتحسين، يتم تخصيص أول X إنت (لا أتذكر كم) دائما في الذاكرة لتنفيذ ل فاتسر حلقة (على سبيل المثال: for (int i =0; i<10; i++) ))

وكمثال على مرجع الكائن، مجرد محاولة لإنشاء ومحاولة طباعته

int[] i = {1,2,3};
System.out.println(i);

سترى أن جافا تعود شيئا بدءا من [I@ . وهو يقول أن هذه النقطة على "مجموعة من إنت" ثم الإشارة إلى الكائن. لا منطقة الذاكرة!




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

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

الجواب على ذلك هو "لا"، كما أنه سيحل إلى حد كبير أي شيء وراء "مرحبا، العالم" وربما حتى ذلك.

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