مقارنة enum في Java: == أم equals()؟ التفاصيل الدقيقة التي لا يُتحدث عنها

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

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

ابدأ الدورة

مقدمة: خطأ قد ترتكبه الآن

\n\n

تخيل الموقف: أنت تكتب بلغة Java، تستخدم التعدادات (enum) وتحتاج لمقارنة قيمتين. تكتب تلقائياً if (day == Day.MONDAY). أو ربما if (day.equals(Day.MONDAY)). فأي الخيارين صحيح؟ وهل هناك فرق أصلاً؟

\n\n

هذا السؤال هو من أكثر الأسئلة شيوعاً على Stack Overflow. آلاف المطورين (من المبتدئين إلى كبار المطورين) تساءلوا عنه. قد يبدو الأمر تافهاً. لكن خلف هذا "التفاهة" يكمن فهم عميق لكيفية عمل JVM، وكيفية بناء enum، ولماذا الأمور في Java ليست دائماً واضحة.

\n\n

في هذه المقالة، سنحسم الأمر مرة وإلى الأبد: كيف تقارن enum في Java بشكل صحيح، ومتى تستخدم ==، ومتى تستخدم equals()، ولماذا أحد هذين الخيارين هو دائماً الخيار الأفضل تقريباً.

\n\n

إجابة مختصرة لغير الصبورين

\n\n

إذا كنت تريد الإجابة الآن — استخدم ==.

\n\n

لكن! قبل أن تغلق المقالة، دعنا نفهم لماذا هذا هو الحال، وما هي المخاطر الخفية التي قد تواجهك. لأن الشيطان، كما هو الحال دائماً، في التفاصيل.

\n\n

لماذا enum ليس مجرد مجموعة من الثوابت؟

\n\n

لفهم الفرق بين == و equals()، عليك أن تتذكر ما هو enum في Java حقاً.

\n\n

كل enum هو فئة كاملة، ترث ضمنياً من java.lang.Enum. كل ثابت من enum هو مثيل ثابت ونهائي من هذه الفئة. JVM يضمن أنه لكل قيمة enum يوجد كائن واحد فقط في الذاكرة.

\n\n

انظر إلى هذا الكود:

\n\n
public enum Day {\n    MONDAY,\n    TUESDAY,\n    WEDNESDAY,\n    THURSDAY,\n    FRIDAY,\n    SATURDAY,\n    SUNDAY\n}
\n\n

عندما يقوم JVM بتحميل هذا enum، فإنه ينشئ 7 كائنات بالضبط. Day.MONDAY هو دائماً نفس الكائن. دائماً. وهذه هي النقطة الأساسية.

\n\n

المقارنة باستخدام ==: لماذا تعمل؟

\n\n

عامل == في Java يقارن المراجع للكائنات. لا ينظر إلى المحتوى — بل يتحقق مما إذا كان المتغيران يشيران إلى نفس الكائن في الذاكرة.

\n\n

نظراً لأن JVM يضمن تفرد كل مثيل من enum، فإن المقارنة باستخدام == لـ enum تعمل بشكل لا تشوبه شائبة:

\n\n
public class EnumComparison {\n    public static void main(String[] args) {\n        Day today = Day.WEDNESDAY;\n        Day anotherDay = Day.WEDNESDAY;\n        \n        // كلا المتغيرين يشيران إلى نفس الكائن في الذاكرة\n        System.out.println(today == anotherDay); // true\n        \n        // مقارنة مع ثابت آخر\n        System.out.println(today == Day.MONDAY); // false\n    }\n}
\n\n

النتيجة:

\n
true\nfalse
\n\n

كل شيء بسيط وأنيق. لكن دعنا نرى ما يحدث تحت الغطاء.

\n\n

لماذا هذا آمن؟ ضمانات JVM

\n\n

مواصفات لغة Java (JLS 8.9) تضمن أن كل قيمة enum تتم تهيئتها مرة واحدة فقط عند تحميل الفئة. لا يمكنك باستخدام الانعكاس (reflection) أو التسلسل (serialization) أو الاستنساخ (cloning) إنشاء نسخة مكررة. حتى لو حاولت استخدام new — سيعطيك المترجم خطأ.

\n\n

لذلك، == لـ enum ليس فقط "يعمل"، بل هو أسرع وأضمن طريقة للمقارنة.

\n\n

المقارنة باستخدام equals(): تعمل، لكن مع بعض التحفظات

\n\n

طريقة equals() تعمل أيضاً. فئة Enum تعيد تعريف equals()، وداخلياً تستخدم ==:

\n\n
// الكود الحقيقي من java.lang.Enum\npublic final boolean equals(Object other) {\n    return this == other;\n}
\n\n

أي أن استدعاء day.equals(Day.MONDAY) في النهاية يفعل نفس الشيء مثل day == Day.MONDAY. لكن هناك فرق مهم:

\n\n

مشكلة null

\n\n

إذا كان المتغير الخاص بك قد يك

المدونات

توصيات الكتب