جافا:لماذا أتلقى رسالة الخطأ "عدم تطابق النوع:لا يمكن التحويل إلى بايت"

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

سؤال

إذا قمت بتعريف متغيرات من النوع بايت أو قصير وحاولت إجراء عمليات حسابية عليها، فستتلقى الخطأ "عدم تطابق النوع:لا يمكن التحويل من int إلى short" (أو بالمقابل "نوع غير متطابق:لا يمكن التحويل إلى بايت").

byte a = 23;
byte b = 34;
byte c = a + b;

في هذا المثال، خطأ الترجمة موجود في السطر الثالث.

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

المحلول

على الرغم من تعريف العوامل الحسابية للعمل على أي نوع رقمي، وفقًا لمواصفات لغة Java (5.6.2 الترويج الرقمي الثنائي)، تتم ترقية المعاملات من النوع byte وshort تلقائيًا إلى int قبل تسليمها إلى المشغلين.

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

byte a = 23;
byte b = 34;
byte c = (byte) (a + b);

إليك سؤال متابعة لمعلمي Java الحقيقيين:لماذا ؟أنواع البايت والقصيرة هي أنواع رقمية جيدة تمامًا.لماذا لا تسمح Java بالعمليات الحسابية المباشرة على هذه الأنواع؟(الإجابة ليست "فقدان الدقة"، حيث لا يوجد سبب واضح للتحويل إلى int في المقام الأول.)

تحديث:يقترح jrudolph أن هذا السلوك يعتمد على العمليات المتوفرة في JVM، وعلى وجه التحديد، يتم تنفيذ عوامل التشغيل ذات الكلمات الكاملة والمزدوجة فقط.وبالتالي، بالنسبة للمشغل على البايتات والشورتات، يجب تحويلها إلى int.

نصائح أخرى

الجواب على سؤال المتابعة الخاص بك هو هنا:

تتم ترقية المعاملات من النوع بايت وقصيرة تلقائيًا إلى int قبل تسليمها إلى المشغلين

لذلك، في المثال الخاص بك، a و b يتم تحويل كلاهما إلى int قبل تسليمها إلى عامل التشغيل +.نتيجة إضافة اثنين ints معًا هو أيضًا int.تحاول بعد ذلك تعيين ذلك int إلى أ byte القيمة تسبب الخطأ بسبب احتمال فقدان الدقة.من خلال تقديم النتيجة بشكل صريح فإنك تقول للمترجم "أعرف ما أفعله".

أعتقد أن الأمر هو أن JVM يدعم نوعين فقط من قيم المكدس:حجم الكلمة وحجم الكلمة مزدوج.

ثم ربما قرروا أنهم سيحتاجون إلى عملية واحدة فقط تعمل على أعداد صحيحة بحجم الكلمة في المكدس.لذلك لا يوجد سوى iadd وimul وما إلى ذلك على مستوى الرمز الثانوي (ولا توجد عوامل تشغيل للبايتات والشورتات).

لذا تحصل على قيمة int كنتيجة لهذه العمليات التي لا تستطيع Java تحويلها بأمان مرة أخرى إلى أنواع البيانات الأصغر حجمًا والقصيرة.لذلك يجبرونك على الإرسال لتضييق القيمة إلى بايت/قصير.

لكن في النهاية أنت على حق:هذا السلوك لا يتوافق مع سلوك ints، على سبيل المثال.يمكنك بسهولة إضافة اثنين من ints وعدم الحصول على أي خطأ إذا تجاوزت النتيجة.

تقوم لغة Java دائمًا بترويج وسيطات العوامل الحسابية إلى int أو long أو float أو double.لذا خذ التعبير:

a + b

حيث a و b من النوع بايت.وهذا اختصار لـ:

(int)a + (int)b

هذا التعبير من النوع int.من الواضح أنه من المنطقي إعطاء خطأ عند تعيين قيمة int لمتغير بايت.

لماذا يتم تعريف اللغة بهذه الطريقة؟لنفترض أن a كان 60 وb كان 70، ثم a+b هو -126 - تجاوز عدد صحيح.كجزء من تعبير أكثر تعقيدًا كان من المتوقع أن يؤدي إلى int، فقد يصبح هذا خطأً صعبًا.تقييد استخدام البايت والتخزين القصير والثوابت لتنسيقات الملفات/بروتوكولات الشبكة والألغاز.

يوجد تسجيل مثير للاهتمام من JavaPolis 2007.يقدم جيمس جوسلينج مثالاً عن مدى تعقيد العمليات الحسابية غير الموقعة (وسبب عدم وجودها في Java).يشير جوش بلوخ إلى أن مثاله يعطي مثالًا خاطئًا في ظل الحساب العادي الموقّع أيضًا.لإجراء عمليات حسابية مفهومة، نحتاج إلى دقة اعتباطية.

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