تحويل ArrayList<String> إلى String[]: 5 أخطاء قاتلة للمبتدئين

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

ArrayList<String> إلى String[]: لا تدع نفسك تُخدع

\n\n

مرحبًا، يا صديقي! إذا كنت تقرأ هذا، فهذا يعني أنك واجهت بالفعل المهمة الكلاسيكية - تحتاج إلى تحويل ArrayList<String> إلى مصفوفة عادية String[]. قد يبدو الأمر بسيطًا؟ تأخذ طريقة toArray()، تستدعيها - وتنتهي. لكن الأمر ليس بهذه السهولة! Java لغة ماكرة، وحتى هذه العملية البسيطة يمكن أن تتحول إلى صداع إذا كنت لا تعرف المخاطر الخفية.

\n\n

على Stack Overflow، حصد هذا السؤال آلاف المشاهدات، وهذا ليس بدون سبب. لقد جمعنا أفضل 5 أخطاء يرتكبها حتى المطورون ذوو الخبرة، وسنوضح لك كيفية تجنبها. هيا بنا!

\n\n

لماذا لا يعمل list.toArray() ببساطة؟

\n\n

دعنا نبدأ مباشرة. لديك قائمة:

\n\n
ArrayList<String> list = new ArrayList<>();\nlist.add("Java");\nlist.add("Python");\nlist.add("C++");
\n\n

تريد الحصول على مصفوفة من السلاسل النصية. أول فكرة تتبادر إلى الذهن هي استدعاء list.toArray(). انظر ماذا سيحدث:

\n\n
Object[] objectArray = list.toArray(); // يعمل، لكنه يُرجع Object[]\n// String[] stringArray = list.toArray(); // خطأ في الترجمة!
\n\n

الخطأ رقم 1: نسيان تحويل الأنواع. الطريقة toArray() بدون وسائط تُرجع Object[] وليس String[]. لن يسمح لك المترجم ببساطة بتعيين Object[] لمتغير من النوع String[]. تحتاج إلى تحويل صريح:

\n\n
String[] stringArray = (String[]) list.toArray(); // ClassCastException في وقت التشغيل!
\n\n

هنا يبدأ الجزء المثير للاهتمام. الخطأ الثاني هو الاعتقاد بأن تحويل الأنواع سينقذ الموقف. ستحصل على ClassCastException، لأنه داخل toArray() يتم إنشاء مصفوفة من النوع Object[] وليس String[]. التحويل لا يغير نوع الكائن - إنه فقط يخبر المترجم: "ثق بي، هذا سلسلة نصية". لكن Java في وقت التشغيل تتحقق وتلقي استثناءً.

\n\n

الطريقة الصحيحة: toArray(new String[0])

\n\n

الطريقة الأكثر شيوعًا وصحة هي تمرير مصفوفة فارغة من النوع المطلوب إلى toArray():

\n\n
String[] stringArray = list.toArray(new String[0]);
\n\n

لماذا يعمل هذا؟ لأن الطريقة toArray(T[] a) هي طريقة عامة (generic). تقبل مصفوفة من النوع T وتُعيد مصفوفة من نفس النوع. إذا كانت المصفوفة الممررة غير كبيرة بما يكفي، تقوم الطريقة بإنشاء مصفوفة جديدة من النوع الصحيح باستخدام الانعكاس (reflection). إذا كان الحجم مناسبًا - تملؤها.

\n\n

الخطأ رقم 3: تمرير مصفوفة بحجم غير صحيح. بعض المبتدئين يكتبون:

\n\n
String[] stringArray = list.toArray(new String[list.size()]);
\n\n

هذا يعمل أيضًا، لكن دعنا نفهم أيهما أفضل. عندما نمرر مصفوفة بحجم list.size()، تقوم الطريقة بملئها وإعادتها. إذا مررنا new String[0] - يتم إنشاء مصفوفة جديدة. قد يبدو، لماذا نضيع الوقت في إنشاء مصفوفة جديدة؟ في الواقع، JVM يحسن إنشاء المصفوفة الفارغة، وفي معظم الحالات يعمل new String[0] بشكل أسرع من new String[list.size()]. لماذا؟ لأنه في الحالة الثانية، يتم إنشاء المصفوفة، ثم تملأ بقيم null، ثم تُعاد كتابتها. عمل إضافي.

\n\n

غالبًا ما تعمل إصدارات JVM الحديثة (Java 8+) على تحسين new String[0] إلى ثابت، مما يجعله أسرع. لكن إذا كنت تعمل مع Java 6 أو 7 - قد يكون الفرق ملحوظًا. على أي حال، أفضل ممارسة هي استخدام new String[0]، إذا لم تكن هناك حاجة لأداء فائق السرعة. لأجزاء الكود الحساسة للسرعة - اختبر كلا الخيارين.

\n\n

المخاطر الخفية: التزامن وتعدد الخيوط

\n\n

الخطأ رقم 4: التحويل في بيئة متعددة الخيوط بدون مزامنة. تخيل: لديك ArrayL

المدونات

توصيات الكتب