জাভাতে এনামগুলিতে == ব্যবহার করা কি ঠিক আছে?


111

==জাভাতে এনামগুলিতে ব্যবহার করা ঠিক আছে , বা আমার ব্যবহার করা দরকার .equals()? আমার পরীক্ষায় ==সর্বদা কাজ করে তবে আমি নিশ্চিত নই যে আমি এর নিশ্চয়তা পেয়েছি। বিশেষত, .clone()এনুমে কোনও পদ্ধতি নেই , তাই আমি জানি না যে এনাম পাওয়া সম্ভব কিনা যার জন্য .equals()আলাদা মানটি ফিরে আসবে ==

উদাহরণস্বরূপ, এটি কি ঠিক আছে:

public int round(RoundingMode roundingMode) {
  if(roundingMode == RoundingMode.HALF_UP) {
    //do something
  } else if (roundingMode == RoundingMode.HALF_EVEN) {
    //do something
  }
  //etc
}

বা আমার কি এটি এইভাবে লিখতে হবে:

public int round(RoundingMode roundingMode) {
  if(roundingMode.equals(RoundingMode.HALF_UP)) {
    //do something
  } else if (roundingMode.equals(RoundingMode.HALF_EVEN)) {
    //do something
  }
  //etc
}


@Asslias এই প্রশ্নটি প্রথম এসেছিল। সম্ভবত মনোযোগের জন্য পতাকা, যেহেতু আমি সত্যই নিশ্চিত নই যে এই দুটি একত্রিত করা উচিত কিনা।
ম্যাট বল

@ ম্যাটবাল আমি মনে করি জেএলএস-এর উদ্ধৃতি দেওয়া আপনার প্রশ্নের উত্তরই সেরা উত্তর, সে কারণেই আমি এইটিকে বন্ধ করতে বেছে নিয়েছি।
Assylias

উত্তর:


149

সবেমাত্র আমার 2 সেন্ট: সুনের দ্বারা প্রকাশিত এনাম.জাবার কোড এবং জেডিকে-র অংশটি এখানে:

public abstract class Enum<E extends Enum<E>>
    implements Comparable<E>, Serializable {

    // [...]

    /**
     * Returns true if the specified object is equal to this
     * enum constant.
     *
     * @param other the object to be compared for equality with this object.
     * @return  true if the specified object is equal to this
     *          enum constant.
     */
    public final boolean equals(Object other) { 
        return this==other;
    }


}

4
ধন্যবাদ! আমি অনুমান করি যে আমি যদি এই কম্পাইলারটি দিয়ে কেবল সেকেন্ডে () প্রবেশ করার চিন্তা করতাম তবে আমি এটি দেখতে পেতাম ...
কিপ

77

হ্যাঁ, == ঠিক আছে - প্রতিটি মানের জন্য কেবল একটি একক রেফারেন্স হওয়ার নিশ্চয়তা রয়েছে।

তবে আপনার রাউন্ড পদ্ধতিটি লেখার আরও ভাল উপায় রয়েছে:

public int round(RoundingMode roundingMode) {
  switch (roundingMode) {
    case HALF_UP:
       //do something
       break;
    case HALF_EVEN:
       //do something
       break;
    // etc
  }
}

এটি করার আরও একটি ভাল উপায় হ'ল এনামের মধ্যে কার্যকারিতাটি রাখা, যাতে আপনি কেবল কল করতে পারেন roundingMode.round(someValue)। এটি জাভা এনামগুলির হৃদয়ে পৌঁছে - এগুলি অন্য কোথাও পাওয়া "নামযুক্ত মান" এর বিপরীতে অবজেক্ট-ওরিয়েন্টেড এনামগুলি।

সম্পাদনা: অনুমানটি খুব পরিষ্কার নয়, তবে ৮.৯ অনুচ্ছেদে বলা হয়েছে:

একটি এনাম ধরণের শরীরে এনাম ধ্রুবক থাকতে পারে। একটি এনাম ধ্রুবক এনাম ধরণের একটি উদাহরণকে সংজ্ঞায়িত করে। একটি এনাম ধরণের এনাম ধ্রুবক দ্বারা সংজ্ঞায়িত ছাড়া অন্য কোনও দৃষ্টান্ত নেই।


আমি এটির জন্য আপনার কথাটি নিতে চাই তবে আপনি যদি এমন কিছু অফিসিয়াল ডকুমেন্টেশনের লিঙ্ক সরবরাহ করতে পারতেন তবে ভাল হত ...
কিপ

বিভিন্ন ক্ষেত্রে যখন প্রচুর ওভারল্যাপ হয় তখন স্যুইচ কার্যকর হয় না। এছাড়াও, রাউন্ডিংমোড java.math এর অংশ, সুতরাং আমি এটিতে কোনও পদ্ধতি যুক্ত করতে পারি না।
কিপ

2
ওহ - এবং আপনি জোন স্কিটকে সন্দেহ করছেন? আপনি এখানে খুব বেশি দিন থাকেন নি;)
জোয়েল কোহর্ন

সুইচ বিবৃতিতে enums? জানতেন না যে এটি সম্ভব হয়েছিল। আমাকে একদিন চেষ্টা করে দেখতে হবে।
লুস্কুবাল

বিমূর্ত পদ্ধতি ব্যবহার করে এনামগুলিতে অন্তর্নিহিত যুক্তি হ'ল এনোমগুলির আসল শক্তি। এটি আপনার কোডকে আরও শক্তিশালী করে তোলে; আপনি যখন ভবিষ্যতে একটি নতুন এনাম মান যুক্ত করবেন, সংকলক আপনাকে প্রাসঙ্গিক যুক্তিটি প্রয়োগ করতে বাধ্য করবে, একাধিক সুইচ স্টেটমেন্টগুলিতে আপনাকে কোনও কেস যুক্ত করতে ভুলবেন না।
অ্যান্ড্রু সোয়ান 21

13

হ্যাঁ, এটি এনামের প্রতিটি মানের জন্য আপনি সিঙ্গলটন উদাহরণ তৈরি করেছেন:

সার্বজনীন বিমূর্ত শ্রেণি রাউন্ডিংমড {
  পাবলিক স্ট্যাটিক ফাইনাল রাউন্ডিংমোড HALF_UP = নতুন রাউন্ডিংমোড ();
  সর্বজনীন স্ট্যাটিক ফাইনাল রাউন্ডিংমোড HALF_EVEN = নতুন রাউন্ডিংমোড ();

  ব্যক্তিগত রাউন্ডিংমোড () {
    // ব্যক্তিগত সুযোগ এই শ্রেণীর বাইরে যে কোনও উপ-টাইপ প্রতিরোধ করে
  }
}

তবে , enumকনস্ট্রাক্ট আপনি বিভিন্ন সুবিধা দেয়:

  • প্রতিটি উদাহরণের স্ট্রাস্টিং () কোডে দেওয়া নামটি মুদ্রণ করে।
  • (অন্য পোস্টে উল্লিখিত হিসাবে,) এনাম টাইপের একটি পরিবর্তনশীল switch-caseনিয়ন্ত্রণ কাঠামো ব্যবহার করে ধ্রুবকের সাথে তুলনা করা যেতে পারে can
  • valuesপ্রতিটি এনুম টাইপের জন্য 'উত্পন্ন' ক্ষেত্রটি ব্যবহার করে গণনার সমস্ত মান জিজ্ঞাসা করা যেতে পারে
  • এখানে বড় এক পরিচয় পরিচয় তুলনা: এনাম মান ক্লোনিং ছাড়াই সিরিয়ালাইজেশন টিকে আছে।

সিরিয়ালাইজেশন হ'ল বড় গোচা ya যদি আমি এনামের পরিবর্তে উপরের কোডটি ব্যবহার করি, তবে পরিচয়ের সাম্য কীভাবে আচরণ করবে তা এখানে:

রাউন্ডিংমোড আসল = রাউন্ডিংমোড Hএইচএলএফ_আপ;
জোড় (রাউন্ডিংমোড.এইএলএফ_ইউপি == আসল); // পাস

বাইটআরআউটআউটপুটস্ট্রিম বাওস = নতুন বাইটআরআউটপুটস্ট্রিম ();
অবজেক্টআউটপুটস্ট্রিম oos = নতুন অবজেক্টআউটপুটস্ট্রিম (বাওস);
oos.writeObject (মূল);
oos.flush ();

বাইটআরআইআইপুট স্ট্রিম বাইস = নতুন বাইটআরআইআইপুট স্ট্রিম (baos.toByteArray ());
অবজেক্টআইপুট স্ট্রিম ois = নতুন অবজেক্টইনপুটস্ট্রিম (বাইস);
রাউন্ডিংমোড deserialized = (রাউন্ডিংমোড) ois.readObject ();

দাবী (রাউন্ডিংমোড.এইএএলএফ_ইউপি == ডিজিসায়ালাইজড); // ব্যর্থ
দাবী (রাউন্ডিংমোড.এইএএলএফ_ইভিএন == ডিজিট্রাইজড); // ব্যর্থ

আপনি এনাম ছাড়াই এই সমস্যাটি সমাধান করতে পারেন , এমন একটি প্রযুক্তি ব্যবহার করে writeReplaceএবং readResolve( http://java.sun.com/j2se/1.4.2/docs/api/java/io/Serializable.html দেখুন ) ...

আমার অনুমানটিটি হ'ল - জাভা আপনাকে সমতা পরীক্ষার জন্য এনাম ভ্যালু'র পরিচয় ব্যবহার করার অনুমতি দেবে না; এটি একটি উত্সাহিত অনুশীলন।


1
সিরিয়ালাইজেশন বাগটি ঠিক করা হয়েছিল। bugs.sun.com/bugdatedia/view_bug.do?bug_id=6277781
ডেভিড আই।

@DavidI। আপডেটের জন্য ধন্যবাদ. এটি একটি খুব বিরক্তিকর বাগ, এবং জেনে রাখা ভাল!
দিলুম রানাতুঙ্গা

1
@ দিলামরানতুঙ্গা আমি ভেবেছিলাম এটি প্রথমে আমার উপর প্রভাব ফেলবে তবে তারা আরএমআই সংযোগের পরে তারা ঠিক কাজ করছে বলে মনে হচ্ছে।
ডেভিড আই।

11

== দুটি বস্তুর রেফারেন্স তুলনা করে। এনামগুলির জন্য, এটির গ্যারান্টি রয়েছে যে কেবলমাত্র একটি উদাহরণ থাকবে এবং সুতরাং যে কোনও দুটি এনামের জন্য একই, == সত্য হবে true

রেফারেন্স:

http://www.ajaxonomy.com/2007/java/making-the-most-of-java-50-enum-tricks

(সান ডক্সে কিছু খুঁজে পেল না)


6

এখানে এমন কিছু দুষ্ট কোড যা আপনাকে আকর্ষণীয় মনে হতে পারে। : ডি

public enum YesNo {YES, NO}

public static void main(String... args) throws Exception {
    Field field = Unsafe.class.getDeclaredField("theUnsafe");
    field.setAccessible(true);
    Unsafe unsafe = (Unsafe) field.get(null);
    YesNo yesNo = (YesNo) unsafe.allocateInstance(YesNo.class);

    Field name = Enum.class.getDeclaredField("name");
    name.setAccessible(true);
    name.set(yesNo, "YES");

    Field ordinal = Enum.class.getDeclaredField("ordinal");
    ordinal.setAccessible(true);
    ordinal.set(yesNo, 0);

    System.out.println("yesNo " + yesNo);
    System.out.println("YesNo.YES.name().equals(yesNo.name()) "+YesNo.YES.name().equals(yesNo.name()));
    System.out.println("YesNo.YES.ordinal() == yesNo.ordinal() "+(YesNo.YES.ordinal() == yesNo.ordinal()));
    System.out.println("YesNo.YES.equals(yesNo) "+YesNo.YES.equals(yesNo));
    System.out.println("YesNo.YES == yesNo " + (YesNo.YES == yesNo));
}

1
@ পিটার আপনি কি এই কোডটির আমদানি অন্তর্ভুক্ত করতে পারেন? খুঁজে পাওয়া যায় না Unsafe.class
rumman0786

3

পলিমারফিক কোডে এনামগুলি দুর্দান্ত জায়গা।

enum Rounding {
  ROUND_UP {
    public int round(double n) { ...; }
  },
  ROUND_DOWN {
    public int round(double n) { ...; }
  };

  public abstract int round(double n);
}

int foo(Rounding roundMethod) {
  return roundMethod.round(someCalculation());
}

int bar() {
  return foo(Rounding.ROUND_UP);
}

1
হ্যাঁ তবে আমি জাভা.ম্যাথ.রউন্ডিংমডের মালিক নই, তাই আমি আমার ক্ষেত্রে এটি করতে পারি না।
কিপ


0

== সাধারণত ঠিক আছে, এবং উভয়রই সুবিধা রয়েছে == এবং .equals()। এস .equals()সহ সামগ্রীর সাথে তুলনা করার সময় আমি ব্যক্তিগতভাবে সর্বদা ব্যবহার করতে পছন্দ করি enum। এই আলোচনাও দেখুন:

জাভা এনাম সদস্যদের তুলনা করছেন: == বা সমান ()?

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.