java تعلم - مقارنة أعضاء التعداد في Java: == أو يساوي ()؟




8 Answers

كلاهما صحيح من الناحية الفنية. إذا نظرت إلى شفرة المصدر الخاصة بـ .equals() ، فهي ببساطة .equals() إلى == .

أنا أستخدم == ، ومع ذلك ، لأن ذلك سيكون آمنة فارغة.

شرح بالعربي

وأنا أعلم أن التعدادات جافا يتم تجميعها لفصول مع منشئات خاصة وحفنة من أعضاء ثابت العامة. عند مقارنة عضوين من تعداد معين ، كنت دائمًا أستخدم .equals() ، على سبيل المثال

public useEnums(SomeEnum a)
{
    if(a.equals(SomeEnum.SOME_ENUM_VALUE))
    {
        ...
    }
    ...
}

ومع ذلك ، صادفت فقط بعض التعليمات البرمجية التي تستخدم عامل equals == بدلاً من .equals ():

public useEnums2(SomeEnum a)
{
    if(a == SomeEnum.SOME_ENUM_VALUE)
    {
        ...
    }
    ...
}

ما هو المشغل الذي يجب أن أستخدمه؟




استخدام == لمقارنة قيم التعداد يعمل لأن هناك كائن واحد فقط لكل ثابت التعداد.

في ملاحظة جانبية ، لا تحتاج في الواقع إلى استخدام == لكتابة رمز آمن فارغ إذا كتبت كلمة equals() كما يلي:

public useEnums(SomeEnum a)
{
    if(SomeEnum.SOME_ENUM_VALUE.equals(a))
    {
        ...
    }
    ...
}

هذا هو أفضل ممارسة تعرف باسم مقارنة الثوابت من اليسار التي يجب أن تتبعها بالتأكيد.




هنا هو اختبار توقيت الخام لمقارنة الاثنين:

import java.util.Date;

public class EnumCompareSpeedTest {

    static enum TestEnum {ONE, TWO, THREE }

    public static void main(String [] args) {

        Date before = new Date();
        int c = 0;

        for(int y=0;y<5;++y) {
            for(int x=0;x<Integer.MAX_VALUE;++x) {
                if(TestEnum.ONE.equals(TestEnum.TWO)) {++c;}
                if(TestEnum.ONE == TestEnum.TWO){++c;}              
            }
        }

        System.out.println(new Date().getTime() - before.getTime());
    }   

}

تعليق من IFs واحد في وقت واحد. فيما يلي مقارنة اثنين من أعلاه في رمز بايت تفكيكها:

 21  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 24  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 27  invokevirtual EnumCompareSpeedTest$TestEnum.equals(java.lang.Object) : boolean [28]
 30  ifeq 36

 36  getstatic EnumCompareSpeedTest$TestEnum.ONE : EnumCompareSpeedTest.TestEnum [19]
 39  getstatic EnumCompareSpeedTest$TestEnum.TWO : EnumCompareSpeedTest.TestEnum [25]
 42  if_acmpne 48

يقوم أول (يساوي) بإجراء مكالمة افتراضية ويقوم باختبار قيمة منطقية الإرجاع من المكدس. يقارن الثاني (==) عناوين الكائنات مباشرة من المكدس. في الحالة الأولى هناك المزيد من النشاط.

ركضت هذا الاختبار عدة مرات مع كل واحد منهما في كل مرة. يكون "==" أسرع من أي وقت مضى.




أفضل استخدام == بدلاً من equals :

السبب الآخر ، بالإضافة إلى الأشياء الأخرى التي تمت مناقشتها هنا ، هو أنه يمكنك إدخال خلل دون أن يدرك ذلك. لنفترض أن لديك هذا التعداد هو نفسه تمامًا ولكن في pacakges منفصلة (إنه ليس شائعًا ، ولكنه قد يحدث):

التعداد الأول :

package first.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

التعداد الثاني:

package second.pckg

public enum Category {
    JAZZ,
    ROCK,
    POP,
    POP_ROCK
}

ثم افترض أنك تستخدم equals مثل next في item.category وهو first.pckg.Category لكنك تستورد التعداد الثاني ( second.pckg.Category ) بدلاً من الأول دون إدراك:

import second.pckg.Category;
...

Category.JAZZ.equals(item.getCategory())

لذلك سوف تحصل على allways false بسبب تعداد مختلف على الرغم من أنك تتوقع حقيقة لأن item.getCategory() هو JAZZ . ويمكن أن يكون من الصعب بعض الشيء أن نرى.

لذلك ، إذا استخدمت بدلاً من ذلك عامل التشغيل == فسيظهر خطأ تجميعي:

لا يمكن تطبيق عامل التشغيل == على "second.pckg.Category"، "first.pckg.Category"

import second.pckg.Category; 
...

Category.JAZZ == item.getCategory() 



التعداد هي عبارة عن فئات تقوم بإرجاع مثيل واحد (مثل singletons) لكل ثابت تعداد معلن بواسطة public static final field (غير قابل للتغيير) بحيث يمكن استخدام عامل == للتحقق من مساواتهم بدلاً من استخدام طريقة equals()




أريد أن أكمل تكملة polygenelubricants:

أنا شخصيا تفضل يساوي (). لكنها بحيرة تحقق التوافق نوع. وهو ما أعتقد أنه قيد مهم.

للحصول على التحقق من التوافق مع الكتابة في وقت التحويل البرمجي ، يمكنك التصريح واستخدام وظيفة مخصصة في التعداد الخاص بك.

public boolean isEquals(enumVariable) // compare constant from left
public static boolean areEqual(enumVariable, enumVariable2) // compare two variable

مع هذا ، لديك ميزة كل من الحل: حماية NPE ، من السهل قراءة التعليمات البرمجية ونوع التحقق من التوافق في وقت التجميع.

كما أوصي بإضافة قيمة غير محددة للتعداد.




السبب enev العمل بسهولة مع == لأن كل حالة محددة هي أيضا مفردة. لذا ستعمل مقارنة الهوية باستخدام == دائمًا.

لكن استخدام == لأنه يعمل مع التعدادات يعني أن كل كودك مقترن بإحكام باستخدام هذا التعداد.

على سبيل المثال: Enums يمكن تنفيذ واجهة. لنفترض أنك تستخدم حاليًا تعدادًا يطبّق Interface1. إذا حدث ذلك في وقت لاحق ، يقوم أحدهم بتغييره أو يقدم طبقة جديدة من Impl1 كتطبيق لنفس الواجهة. ثم ، إذا بدأت في استخدام أمثلة من Impl1 ، سيكون لديك الكثير من التعليمات البرمجية لتغيير واختبار بسبب الاستخدام السابق ==.

ومن ثم ، فمن الأفضل اتباع ما يعتبر ممارسة جيدة ما لم يكن هناك أي مكسب مبرر.




أود أن أسلط الضوء صراحةً على هذا الاختلاف المحدد بين طريقة == مشغل و equals() :

يقصد منه الأسلوب equals() للتحقق مما إذا كانت محتويات الكائن (الكائنات) التي يشير المتغير (المتغيرات) المرجعي فيها إلى (s) هي نفسها.

يقوم عامل التشغيل == بالتحقق مما إذا كان المتغير (المراجع) المشار إليه يشير إلى (ق) إلى نفس الكائن .

والأمر متروك للفئة التنفيذية لتقديم هذا التمايز حسب الحاجة في التطبيق.

وإلا فسيكون السلوك الافتراضي كما هو منصوص عليه في فئة Object (في Java) حيث تم شرحه في http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Object.html#equals(java.lang.Object) :

يطبق أسلوب equals للفئة Object أكثر علاقة التكافؤ الممكنة التمييز على الكائنات؛ أي ، لأي قيم مرجعية غير فارغة x و y ، ترجع هذه الطريقة true إذا وفقط إذا كانت x و y تشير إلى نفس الكائن ( x == y يحتوي على القيمة true ).




Related

java enums

Tags

java   enums