لماذا لا تكتشف المهمة المركبة في Java مشاكل التجاوز؟

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

سؤال

لصدمتي، اتضح أن الكود التالي سيتم تجميعه دون أي تحذيرات:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value += increment;
}

حيث أن هذا يعطي خطأ في وقت الترجمة، كما تتوقع:

public void test()
{
    int value = 2000000000;
    long increment = 1000000000;
    value = value + increment;
}

لقد قمت بفحصه وبالفعل، JLS (القسم 15.26.2) يقول هذا:

تعبير تعيين مركب للنموذج E1 OP = E2 يعادل E1 = (T) ((E1) OP (E2)) ، حيث T هو نوع E1 ، باستثناء أن E1 يتم تقييمها مرة واحدة فقط.

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

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

المحلول

href="http://aloshbennett.wordpress.com/2008/09/13/2008/09/13/2008/09/13/2008/09/13/APCOMPOUND-ASSIGNMEMENT-OPERATION-APEEPE-POTING/"Explanation:

عند إجراء مهمة (مقتطف التعليمات البرمجية الأول)، يفرض Java التحقق من النوع لأن LHS و RHS قد تكون مستقلة عن بعضها البعض.

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

نصائح أخرى

يتم تحديد عوامل التعيين المركب بواسطة JLS (15.26.2) على النحو التالي:

"تعبير إسناد مركب للنموذج E1 op= E2 يعادل

      E1 = (T)((E1) op (E2))`, 

حيث T هو نوع E1، فيما عدا أنه يتم تقييم E1 مرة واحدة فقط."

في هذه الحالة E1 هو من النوع int E2 من النوع long, ، والمرجع هو +.لذلك هذا يعادل:

value = (int)(value + increment);

إضافة ان int و أ long يعطي long ثم يتم إعادته إلى ملف int قبل التكليف.كل هذا جيد، وبالتالي لا يوجد خطأ في التجميع.

الفرق بين هذا والمهمة البسيطة (أي. value = value + increment;)، هو أن المهمة البسيطة لا تحتوي على طباعة.


حسنا اذا لماذا هل عرفوها بهذه الطريقة؟

أعتقد أن السبب هو عمل أمثلة مثل هذا العمل:

    byte b = ...
    b += 1;

بدون الطباعة، b += 1 سيكون خطأ في الترجمة وستحتاج إلى كتابته على النحو التالي:

    b += (byte) 1;

قد قام هذا الرابط بتحليل المشكلة التي طرحتها.

p> سلوك متفاوت من أجل الخسارة المحتملة الدقة

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

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