تعتبر مشكلة التعبئة التلقائية وملاءمة الالتفاف مشكلة شائعة في Java. اليوم سوف نلقي نظرة على بعض المشكلات في التعبئة والملابس. تتحدث هذه المقالة أولاً عن الأشياء الأساسية حول التعبئة واللصق ، ثم ألقِ نظرة على المشكلات المتعلقة بالتعبئة والملاحظة التي يتم مواجهتها غالبًا في الاختبار الكتابي أدناه.
1. ما هو التعبئة؟ ما هو unboxing؟
في المقالة السابقة ، توفر Java أنواع التفاف المقابلة لكل نوع بيانات أساسي. بالنسبة إلى سبب توفير أنواع الغلاف لكل نوع بيانات أساسي ، فلن يتم شرحه هنا. يمكن للأصدقاء المهتمين استشارة المعلومات ذات الصلة. قبل Java SE5 ، إذا كنت ترغب في إنشاء كائن عدد صحيح بقيمة 10 ، يجب عليك القيام بذلك:
نسخة الكود كما يلي:
عدد صحيح I = عدد صحيح جديد (10) ؛
منذ Java SE5 ، يتم توفير ميزة الملاكمة التلقائية. إذا كنت ترغب في إنشاء كائن عدد صحيح بقيمة 10 ، فأنت بحاجة فقط إلى القيام بذلك:
نسخة الكود كما يلي:
عدد صحيح i = 10 ؛
في هذه العملية ، سيتم إنشاء كائن INTEGER المقابل تلقائيًا بناءً على القيمة العددية ، والتي يتم التعبئة.
إذن ما هو unboxing؟ كما يوحي الاسم ، فإنه يتوافق مع التعبئة ، والتي تقوم تلقائيًا بتحويل نوع الغلاف إلى نوع البيانات الأساسي:
نسخة الكود كما يلي:
عدد صحيح i = 10 ؛ // التعبئة
int n = i ؛ // unbox
بعبارة ببساطة ، يعني التعبئة تلقائيًا تحويل نوع البيانات الأساسي إلى نوع الغلاف ؛ يعني إلغاء اللاصداقي تحويل نوع الغلاف إلى نوع البيانات الأساسي.
الجدول التالي هو نوع الغلاف المقابل لنوع البيانات الأساسية:
2. كيف يتم تنفيذ التعبئة والتعبئة؟
بعد فهم المفاهيم الأساسية للتعبئة في القسم السابق ، سيفهم هذا القسم كيف يتم تنفيذ التعبئة والملاحظة.
لنأخذ فئة interger كمثال ، ونرى قطعة رمز أدناه:
الفئة العامة الرئيسية {public static void main (string [] args) {Integer i = 10 ؛ int n = i ؛}}بعد إزالة تجميع ملف الفصل ، ستحصل على المحتوى التالي:
من محتوى Bytecode الذي تم الحصول عليه عن طريق إلغاء تجميع ، يمكن ملاحظة أن طريقة ValueOF (int) في عدد صحيح تلقائيًا عند التعبئة. عند إلغاء الاكتئاب ، يتم استدعاء طريقة Intvalue من عدد صحيح تلقائيًا.
البعض الآخر متشابه ، مثل المزدوج أو الطابع. يمكن للأصدقاء الذين لا يؤمنون به تجربته يدويًا بأنفسهم.
لذلك ، يمكن تلخيص عملية تنفيذ التعبئة والملاحظة في جملة واحدة:
يتم تنفيذ عملية الملاكمة عن طريق استدعاء طريقة ValueOF للركب ، في حين يتم تنفيذ عملية إلغاء التزامن عن طريق استدعاء طريقة XXXValue للركب. (يمثل xxx نوع البيانات الأساسية المقابلة).
3. الأسئلة ذات الصلة خلال المقابلة
على الرغم من أن معظم الناس واضحون بشأن مفاهيم التعبئة والملابس ، إلا أنهم قد لا يكونون قادرين على الإجابة على أسئلة حول التعبئة والملابس أثناء المقابلات والاختبارات المكتوبة. فيما يلي بعض أسئلة المقابلة الشائعة المتعلقة بالتعبئة/إلغاء الاضطراب.
1. ما هي نتيجة الإخراج للرمز التالي؟
الفئة العامة الرئيسية {public static void main (string [] args) {Integer i1 = 100 ؛ integer i2 = 100 ؛ integer i3 = 200 ؛ integer i4 = 200 ؛ system.out.println (i1 == i2) ؛ system.out.println (i3 == i4) ؛}}}}}}}}}}}}}}}} ربما سيقول بعض الأصدقاء أنهم سوف يخرجون خطأ ، أو سيقول بعض الأصدقاء أنهم سوف يخرجون صحيحًا. ولكن في الواقع الناتج هو:
حقيقي
خطأ شنيع
لماذا تحدث مثل هذه النتيجة؟ تظهر نتائج الإخراج أن I1 و I2 يشيران إلى نفس الكائن ، بينما يشير I3 و I4 إلى كائنات مختلفة. في هذه المرحلة ، تحتاج فقط إلى إلقاء نظرة على الكود المصدر لمعرفة الحقيقة. الرمز التالي هو التنفيذ المحدد لطريقة قيمة integer:
القيمة العددية الثابتة العامة (int i) {if (i> = -128 && i <= integercache.high) إرجاع integercache.cache [i + 128] ؛ elsereturn new integer (i) ؛} تنفيذ فئة integercache هو:
integercache static integercache {static final int high ؛ ذاكرة التخزين المؤقت النهائية الثابتة [] ؛ ثابت {final int low = -128 ؛ // يمكن تكوين القيمة العالية بواسطة propertyInt h = 127 ؛ إذا (integercacheighpropvalue! = null) {// استخدم long.decode هنا لتجنب inview that that inte inte inte in inte in inte in inte in inte in inte in inte tiledistint tiledistint that inte inte in in inte. long.decode (integercachehighpropvalue) .intvalue () ؛ i = math.max (i ، 127) ؛ // الحد الأقصى لحجم الصفيف هو integer.max_valueh = math.min (i ، integer.max_value - -low) ؛} عالية = h ؛ K <cache.length من هاتين القطعتين من الكود ، عند إنشاء كائن عدد صحيح من خلال طريقة ValueOF ، إذا كانت القيمة بين [-128 ، 127] ، يتم إرجاع مرجع إلى الكائن الموجود بالفعل في integercache.cache ؛ خلاف ذلك ، يتم إنشاء كائن عدد صحيح جديد.
في الكود أعلاه ، تكون قيم I1 و I2 هي 100 ، لذلك سيتم أخذ الكائنات الموجودة مباشرة من ذاكرة التخزين المؤقت ، لذلك تشير I1 و I2 إلى نفس الكائن ، بينما يشير I3 و I4 إلى كائنات مختلفة على التوالي.
2. ما هي نتيجة الإخراج للرمز التالي؟
الفئة العامة الرئيسية {public static void main (string [] args) {double i1 = 100.0 ؛ double i2 = 100.0 ؛ double i3 = 200.0 ؛ double i4 = 200.0 ؛ system.out.println (i1 == i2) ؛ system.out.println (i3 == i4) ؛}}}}}}}}}}}}}}}}}}} ربما يعتقد بعض الأصدقاء أن نتيجة الإخراج هي نفس السؤال أعلاه ، ولكن في الواقع ليس كذلك. الإخراج الفعلي هو:
خطأ شنيع
خطأ شنيع
بالنسبة للسبب المحدد ، يمكن للقراء التحقق من تنفيذ قيمة الفئة المزدوجة.
هنا سأشرح فقط لماذا تعتمد طريقة ValueOF للفئة المزدوجة تطبيقًا مختلفًا عن طريقة ValueOF لفئة INTEGER. الأمر بسيط للغاية: عدد قيم عدد صحيح في نطاق معين هو محدود ، لكن أرقام النقاط العائمة ليست كذلك.
لاحظ أن تنفيذ أساليب قيمة عدد صحيح ، بايت ، بايت ، شخصية ، وطويلة متشابهة.
تنفيذ طريقة قيمة Double و Float متشابهة.
3. ما هي نتيجة الإخراج للرمز التالي:
الفئة العامة الرئيسية {public static void main (string [] args) {boolean i1 = false ؛ boolean i2 = false ؛ boolean i3 = true ؛ boolean i4 = true ؛ system.out.println (i1 == i2) ؛ system.out.println (i3 == i4) ؛}}}}}}}}}}}}}}}}} نتيجة الإخراج هي:
حقيقي
حقيقي
أما بالنسبة لسبب هذه النتيجة ، فستكون واضحًا أيضًا في لمحة بعد قراءة الكود المصدري لفئة Boolean. فيما يلي التنفيذ المحدد لطريقة قيمة Boolean:
القيمة المنطقية الثابتة العامة (منطقية ب) {return (b؟ صحيح: خطأ) ؛} وما هو صحيح وكاذب؟ يتم تعريف 2 خصائص الأعضاء الثابتة في منطقية:
Public Static Final Boolean True = New Boolean (True) ؛/** * الكائن <Code> Boolean </code> المقابل لقيمة * Primitive * false </code>. */public static final boolean false = new Boolean (false) ؛
في هذه المرحلة ، يجب على الجميع أن يفهم لماذا يكون الإخراج أعلاه صحيحًا.
4. تحدث عن الفرق بين عدد صحيح i = عدد صحيح جديد (xxx) و integer i = xxx ؛
بالطبع ، ينتمي هذا الموضوع إلى نوع واسع نسبيًا. ولكن يجب الرد على النقاط الرئيسية. اسمحوا لي أن ألخص الاختلافين التاليين:
1) لن تؤدي الطريقة الأولى إلى تشغيل عملية الملاكمة التلقائية ؛ في حين أن الطريقة الثانية سوف تؤدي ؛
2) الفرق في كفاءة التنفيذ واستخدام الموارد. الطريقة الثانية لكفاءة التنفيذ واستخدام الموارد أفضل من الأول بشكل عام (لاحظ أن هذا ليس مطلقًا).
5. ما هي نتيجة الإخراج للبرنامج التالي؟
الفئة العامة الرئيسية {public static void main (string [] args) {Integer a = 1 ؛ integer b = 2 ؛ integer c = 3 ؛ integer d = 3 ؛ integer e = 321 ؛ integer f = 321 ؛ long g = 3l ؛ long h = 2l ؛ system.out.println (c == d) ؛ system.out.println (e == f) ؛ system.out.println (c == (a+b)) ؛ system.out.println (c.equals (a+b)) ؛ system.out.println (g == (a+b)) ؛ system.out.printl (g.equals) ؛ لا تنظر إلى نتائج الإخراج أولاً ، سوف يفكر القراء في نتائج الإخراج لهذا الرمز لأنفسهم. ما تجدر الإشارة إليه هنا هو أنه عندما تكون المعاملتين لمشغل "==" تشير إلى نوع الغلاف ، فإنه يقارن ما إذا كان المؤشر هو نفس الكائن ، وإذا كان أحد المعاملات هو التعبير (أي ، يحتوي على عمليات حسابية) ، فإنه يقارن القيم العددية (التي ستؤدي إلى عملية غير المربع التلقائي). بالإضافة إلى ذلك ، بالنسبة لأنواع الغلاف ، لا تؤدي طريقة Equals تحويل النوع. بعد فهم هذه النقطتين ، ستكون نتائج الإخراج أعلاه واضحة في لمحة:
حقيقي
خطأ شنيع
حقيقي
حقيقي
حقيقي
خطأ شنيع
حقيقي
لا شك في نتائج الإخراج الأول والثاني. في الجملة الثالثة ، نظرًا لأن A+B يحتوي على عمليات حسابية ، فإنه يؤدي إلى تشغيل عملية إلغاء التزام التلقائي (سيتم استدعاء طريقة Intvalue) ، وبالتالي فإنها تقارن ما إذا كانت القيم متساوية. بالنسبة إلى C.equals (A+B) ، سيتم تشغيل عملية إلغاء التزام التلقائي أولاً ، ثم يتم تشغيل عملية التعبئة التلقائية. وهذا يعني ، A+B ، سيقوم كل منهم باستدعاء طريقة Intvalue ، وبعد الحصول على القيمة بعد عملية الإضافة ، سيتم استدعاء طريقة integer.valueof ، ثم سيتم إجراء مقارنة متساوية. وينطبق الشيء نفسه على ما يلي ، ولكن الانتباه إلى نتائج الإخراج الثاني إلى الأخير (إذا كانت القيمة من النوع int ، فإن عملية الملاكمة تستدعي integer.valueof ؛ إذا كانت من النوع الطويل ، فإن طريقة الملاكمة تستدعي long.valueof).
ما ورد أعلاه هو فهم عميق للتعبئة واللصق في جافا التي قدمها لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!