जावा का बूलियन वर्ग - एक एनम क्यों नहीं?


11

यह मुझे लगता है कि बुलियन वर्ग एक आदर्श के रूप में लागू होने वाला एक आदर्श उम्मीदवार है।

स्रोत कोड को देखते हुए, अधिकांश वर्ग स्थिर विधियां हैं जिन्हें एक एनम में अपरिवर्तित किया जा सकता है, बाकी एक एनम के रूप में बहुत सरल हो जाते हैं। मूल (टिप्पणियों और स्थिर विधियों को हटाएं) की तुलना करें:

public final class Boolean implements java.io.Serializable,
                                      Comparable<Boolean>
{
   public static final Boolean TRUE = new Boolean(true);
  public static final Boolean FALSE = new Boolean(false);
   private final boolean value;
   public Boolean(boolean value) {
       this.value = value;
   }
   public Boolean(String s) {
       this(toBoolean(s));
   }
   public boolean booleanValue() {
       return value;
   }
   public String toString() {
       return value ? "true" : "false";
   }
   public int hashCode() {
       return value ? 1231 : 1237;
   }
   public boolean equals(Object obj) {
       if (obj instanceof Boolean) {
           return value == ((Boolean)obj).booleanValue();
       }
       return false;
   }
   public int compareTo(Boolean b) {
       return compare(this.value, b.value);
   }
}

एक enum संस्करण के साथ:

public enum Boolean implements Comparable<Boolean>
{
   FALSE(false), TRUE(true);
   private Boolean(boolean value) {
       this.value = value;
   }
   private final boolean value;
   public boolean booleanValue() {
       return value;
   }

   public String toString() {
       return value ? "true" : "false";
   }
}

क्या कोई कारण है कि बूलियन एक एनम नहीं बन सकता है?

यदि यह बराबर () विधि को ओवरराइड करने के लिए सूर्य कोड है, तो यह दोनों मूल्यों के संदर्भों की तुलना करने से पहले उनके मूल्यों की तुलना करने की एक बहुत ही मौलिक जांच को याद कर रहा है। यह है कि मुझे लगता है कि बराबर () विधि होनी चाहिए:

   public boolean equals(Object obj) {

       if (this == obj) {
          return true;
       }

       if (obj instanceof Boolean) {
           return value == ((Boolean)obj).booleanValue();
       }
       return false;
   }

4
क्या आप एक बूलियन के लिए एक और मूल्य पसंद करते हैं जो सही या गलत नहीं है?

1
@ मिचेल्ट एनम को 2 से अधिक मान रखने की आवश्यकता नहीं है। यह जावा में किसी भी तरह का व्यर्थ होगा क्योंकि इसमें बूलियन ( if) प्रसंस्करण के लिए एक विशेष विवरण है ( लेकिन एक वैचारिक / प्रकार के दृष्टिकोण से देखें) बूलियन और एनम दोनों राशि प्रकार के उदाहरण हैं, इसलिए मुझे लगता है कि यह पूछना उचित है कि वे क्यों हैं 'उनके बीच की खाई को पाटना।
डोभाल

1
नोट: आप इसे लागू करने से चूक गए हैं valueOf(String)(जो कि एनम के मूल्य के साथ संघर्ष करेगा) और इसके पीछे का जादू getBooleanइसे बना सकता है ताकि यह Boolean.valueOf("yes")झूठे के बजाय सच हो। जो दोनों 1.0 कल्पना का हिस्सा हैं और उपयुक्त पश्चगामी संगतता की आवश्यकता होगी।

8
@MichaelT FileNotFound बेशक!
फेलो

जवाबों:


13

ठीक है, मुझे लगता है कि मैं यह तर्क देते हुए शुरू कर सकता हूं कि जावा प्रोग्रामिंग भाषा को जावा प्रोग्रामिंग भाषा में जेडडीके 1.5 तक जोड़ा नहीं गया था और इसलिए यह समाधान शुरुआती दिनों में भी एक विकल्प नहीं था जब बूलियन वर्ग को परिभाषित किया गया था।

कहा जा रहा है, जावा के पास रिलीज के बीच पीछे की संगतता बनाए रखने की प्रतिष्ठा है और इसलिए, भले ही हम, आज, आपके समाधान को एक अच्छा विकल्प के रूप में मान सकते हैं, हम इसे पुराने बूलियन का उपयोग करके पहले से ही कोड की हजारों लाइनों को तोड़ने के बिना नहीं कर सकते। कक्षा।


3
आपको जावा 1.0 भाषा की युक्ति java.lang.Boolean मदद के लिए मिल सकती है। new Boolean("True")और new Boolean("true")भी काल्पनिक enum कार्यान्वयन के साथ कुछ समस्या हो सकती है।

ऐसा लगता है कि कई (अपरिवर्तनीय) ऑब्जेक्ट्स को अनुमति देना गलत है, और इसलिए बूलियन पर प्रदान किए गए कंस्ट्रक्टर्स का उपयोग करना एक अच्छा विचार नहीं है - जैसा कि एपीआई प्रलेखन कहता है।
हाईलैंड मार्क

भाषा युक्ति इस तरह के प्रश्न से मदद नहीं करेगी क्योंकि यह कक्षाओं के कार्यान्वयन को निर्दिष्ट नहीं करता है। विनिर्देशन को लागू करने के लिए यह सबसे अच्छा है।
हाईलैंड मार्क

13

कुछ चीजें हैं जो काम नहीं करती हैं, और जब आप जावा के बूलियन की पिछली कार्यक्षमता से उनकी तुलना करते हैं तो आश्चर्यजनक तरीके से काम नहीं करते हैं।

हम मुक्केबाजी को अनदेखा करने जा रहे हैं क्योंकि 1.5 के साथ कुछ जोड़ा गया था। हाइपोथेटिक रूप से, अगर सूर्य चाहते थे कि वे enum Booleanवैसा ही व्यवहार कर सकें जैसा कि बॉक्सिंग पर किया जाता है class Boolean

फिर भी, अन्य आश्चर्यजनक (कोडर के लिए) तरीके हैं जो पहले के वर्ग की कार्यक्षमता की तुलना में अचानक टूट जाएंगे।

ValueOf (स्ट्रिंग) समस्या

इसका एक सरल उदाहरण है:

public class BooleanStuff {
    public static void main(String args[]) {
        Boolean foo = Boolean.valueOf("TRUE");
        System.out.println(foo);
        foo = Boolean.valueOf("TrUe");
        System.out.println(foo);
        foo = Boolean.valueOf("yes");  // this is actually false
        System.out.println(foo);

        // Above this line is perfectly acceptable Java 1.3
        // Below this line takes Java 1.5 or later

        MyBoolean bar;
        bar = MyBoolean.valueOf("FALSE");
        System.out.println(bar);
        bar = MyBoolean.valueOf("FaLsE");
        System.out.println(bar);
    }

    enum MyBoolean implements Comparable<MyBoolean> {
        FALSE(false), TRUE(true);
        private MyBoolean(boolean value) { this.value = value; }
        private final boolean value;
        public boolean booleanValue() { return value; }
        public String toString() { return value ? "true" : "false"; }
    }
}

इस कोड का रन देता है:

सच
सच
असत्य
असत्य
थ्रेड में अपवाद "मुख्य" java.lang.IllegalArgumentException: कोई एनम निरंतर बूलियनस्टफ़। MBBeanean.FaLsE
    java.lang.Enum.valueOf (Enum.java:236) पर
    बूलियनस्टाफ $ MyBoolean.valueOf (बूलियनस्टफ.जवा:17) पर
    BooleanStuff.main (बूलियन स्टफ.जावा:13)

समस्या यहाँ है कि मैं के माध्यम से कुछ भी है कि नहीं है पारित नहीं हो सकता है TRUEया FALSEकरने के लिए valueOf(String)

यह ठीक है ... हम इसे अपने तरीके से ओवरराइड करेंगे ...

    public static MyBoolean valueOf(String arg) {
        return arg.equalsIgnoreCase("true") ? TRUE : FALSE;
    }

लेकिन ... यहाँ एक समस्या है। आप एक स्थिर विधि को ओवरराइड नहीं कर सकते

और इसलिए, सभी कोड जो इधर true- उधर से गुजर रहे हैं या Trueकुछ अन्य मामले मिश्रित हो गए हैं - और एक रनटाइम अपवाद के साथ काफी शानदार होगा।

ValueOf के साथ कुछ और मज़ेदार

कुछ अन्य बिट्स हैं जो बहुत अच्छी तरह से काम नहीं करते हैं:

public static void main(String args[]) {
    Boolean foo = Boolean.valueOf(Boolean.valueOf("TRUE"));
    System.out.println(foo);

    MyBoolean bar = MyBoolean.valueOf(MyBoolean.valueOf("FALSE"));
    System.out.println(bar);
}

इसके लिए foo, मुझे पहले से ही एक बॉक्सिंग वैल्यू बॉक्सिंग के बारे में एक चेतावनी मिलती है। हालाँकि, बार के लिए कोड एक सिंटैक्स त्रुटि है:

त्रुटि: (:, २४) जावा: मूल्य के लिए कोई उपयुक्त विधि नहीं मिली (बूलियन स्टफ.म्यबुलियन)
    पद्धति BooleanStuff.MyBoolean.valueOf (java.lang.String) लागू नहीं है
      (वास्तविक तर्क BooleanStuff.MyBoolean को java.lang में परिवर्तित नहीं किया जा सकता है। विधि मंगलाचरण रूपांतरण के द्वारा)
    विधि java.lang.Enum.valueOf (java.lang.Class, java.lang.String) लागू नहीं है
      (तर्कों से त्वरित नहीं हो सकता क्योंकि वास्तविक और औपचारिक तर्क सूचियां लंबाई में भिन्न होती हैं)

यदि हम उस वाक्य रचना त्रुटि को एक Stringप्रकार से वापस ले लेते हैं :

public static void main(String args[]) {
    Boolean foo = Boolean.valueOf(Boolean.valueOf("TRUE"));
    System.out.println(foo);

    MyBoolean bar = MyBoolean.valueOf(MyBoolean.valueOf("FALSE").toString());
    System.out.println(bar);
}

हमें अपनी रनटाइम त्रुटि वापस मिल जाती है:

सच
थ्रेड में अपवाद "मुख्य" java.lang.IllegalArgumentException: कोई एनम निरंतर बूलियनस्टफ़। MyBoolean.false
    java.lang.Enum.valueOf (Enum.java:236) पर
    बूलियनस्टाफ $ MyBoolean.valueOf (बूलियनस्टफ.जवा:11) पर
    BooleanStuff.main (BooleanStuff.java:7)

कोई ऐसा क्यों लिखेगा? डन्नो ... लेकिन इसका कोड जो काम करता था और अब काम नहीं करेगा।


मुझे गलत मत समझो, मैं वास्तव में किसी भी अपरिवर्तनीय वस्तु की केवल एक प्रति के विचार को पसंद करता हूं। एनम इस समस्या को हल करता है। मैंने व्यक्तिगत रूप से विक्रेता कोड का सामना किया है जिसमें विक्रेता कोड से कीड़े थे जो कुछ इस तरह दिखता था:

if(boolValue == new Boolean("true")) { ... }

यह कभी काम नहीं किया (नहीं, मैंने इसे ठीक नहीं किया क्योंकि गलत स्थिति कहीं और तय की गई थी, और इसे ठीक करने से यह अजीब तरीके से टूट गया था कि मेरे पास वास्तव में डिबग करने का समय नहीं था) । यदि यह एक एनुम होता, तो वह कोड इसके बजाय काम करता।

हालाँकि, Enum के आस-पास के सिंटैक्स की आवश्यकताएं (केस संवेदी - पीछे enumConstantDirectory में खोदना valueOf, रनटाइम त्रुटियाँ जो अन्य enums के लिए उस तरह से काम करने की आवश्यकता होती हैं) और जिस तरह से स्थैतिक तरीके काम करते हैं वह कई चीजों को तोड़ने का कारण बनता है जो इसे रोकता है एक बूलियन के प्रतिस्थापन में एक बूंद होना।


1
यदि कोई डिज़ाइन करता है, तो एक नई भाषा को स्क्रैच करने से कि जावा कैसे काम करता है (और नहीं करता) के ज्ञान के साथ, बूलियन ऑब्जेक्ट प्रकार संरचना की तरह एक एनुम है ... यह अभी जावा के साथ कैसे काम करता है, इसके साथ बिल्कुल फिट नहीं है। मुझे यकीन है कि कुछ भाषा डिजाइनर इसके लिए खुद को लात मार रहे हैं। यदि कोई जावा 8 से शुरू हो सकता है और इंटरफेस में डिफ़ॉल्ट तरीके जैसी चीजें हो सकती हैं, तो मुझे यकीन है कि जावा के बहुत सारे मिसफिट काफी साफ-सुथरे हो सकते हैं - साथ ही मैं वास्तव में इसकी सराहना कर पा रहा हूं कुछ जावा 1.3 कोड और अभी भी इसे 1.8 में संकलित करते हैं - और जहां हम अभी हैं।

यह एक विधि ofया fromउचित javadoc जोड़ने के लिए बहुत मुश्किल नहीं होता ।
23

@ जाइलिस अन्य जावा कोड के बहुत से कन्वेंशन है valueOfऔर बूलियन.वेल्यूऑफ () 1.0 के बाद से है । या तो Enums एक स्थिर विधि के रूप में valueOf का उपयोग करने में सक्षम नहीं होगा, या बूलियन को इसके उपयोग की तुलना में एक अलग विधि की आवश्यकता होगी। या तो टूट जाता है सम्मेलन या अनुकूलता करना - और नहीं होने बूलियन होना एक enum टूट जाता है न। इस से, चुनाव काफी सरल है।

"लेकिन ... यहाँ एक समस्या है। आप एक स्थिर विधि को ओवरराइड नहीं कर सकते।" आप कुछ भी "ओवरराइडिंग" नहीं कर रहे हैं - विधि वैसे भी सुपरक्लास में मौजूद नहीं है। इसके बजाय समस्या यह है कि सभी एनमों के लिए विधि स्वचालित रूप से परिभाषित है, और आप इसे फिर से परिभाषित नहीं कर सकते हैं।
user102008

"फू के लिए, मुझे पहले से ही एक बॉक्सिंग वैल्यू बॉक्सिंग के बारे में एक चेतावनी मिलती है। हालांकि, बार के लिए कोड एक सिंटैक्स त्रुटि है:" यह एक गलत तुलना है। में Boolean.valueOf(Boolean.valueOf("TRUE")), दो अलग-अलग valueOf विधियाँ हैं: valueOf(String)और valueOf(boolean)। सिंटेक्स त्रुटि है, क्योंकि आप को लागू करने की भूल गया valueOf(boolean)में MyBoolean। इसके बाद दोनों कॉल के बीच में आटुनबॉक्सिंग है, जो भाषा में हार्डकोड के लिए है, Booleanलेकिन MyBooleanअगर आपने valueOf(boolean) MyBoolean.valueOf(MyBoolean.valueOf("FALSE").booleanValue())काम नहीं किया
user102008

2

सबसे अधिक संभावना है क्योंकि आदिम booleanप्रकार एक नहीं है Enum, और आदिम प्रकारों के बॉक्सिंग संस्करण उनके अनबॉक्स संस्करण के लिए लगभग समान रूप से व्यवहार करते हैं। उदाहरण के लिए

Integer x = 5;
Integer y = 7;
Integer z = x + y;

(प्रदर्शन समान नहीं हो सकता है, लेकिन यह एक अलग विषय है।)

अगर आप लिख सकते हैं तो यह अजीब होगा:

Boolean b = Boolean.TRUE;
switch (b) {
case Boolean.TRUE:
    // do things
    break;
case Boolean.FALSE:
    // do things
    break;
}

लेकिन नहीं:

boolean b = true;
switch(b) {
case true:
    // do things
    break;
case false:
    // do things
    break;
}  

1
यदि आप ऐसा विवरण दिखाना चाहते हैं जो किसी एनम के साथ काम नहीं करेगा।

@MichaelT मुझे लगता है कि कंपाइलर अभी भी इसे अनबॉक्स करने में सक्षम होगा और ifजैसा वर्तमान में करता है वैसा ही काम करेगा। दूसरी ओर तथ्य यह है कि आप अतिरिक्त कार्यक्षमता जोड़ दिया है करने के लिए की अनदेखी करने का कोई तरीका नहीं है Booleanकि booleanनहीं है।
डोभाल

वाह ... आप जावा में बुलियन के लिए स्विच स्टेटमेंट नहीं लिख सकते हैं? वह पागल है।
थॉमस एडिंग

बॉक्सिंग कक्षाएं केवल अनबॉक्सिंग के कारण आदिम की तरह कार्य करती हैं। पूर्णांक में एक + ऑपरेटर नहीं होता है।
हाइलैंड मार्क

@HighlandMark यह सच है, लेकिन मेरी बात यह है कि वे यह सुनिश्चित करने के लिए महान दर्द से गुजरे कि बॉक्सिंग प्रकार उनके आदिम समकक्षों के समान ही उपयोग करने योग्य थे। अनबॉक्सिंग कुछ ऐसा है जिसे उन्हें लागू करना था, यह मुफ्त में नहीं आता है।
डोभाल

0

valueOfजारी करने के अलावा (जो कि जावा स्तर पर एक मुद्दा है, यह जेवीएम स्तर पर ठीक काम कर सकता है), ऐसा इसलिए Booleanहै क्योंकि इसमें सार्वजनिक कंस्ट्रक्टर है। यह एक बुरा विचार था, वर्तमान में पदावनत, लेकिन यह एक है जो यहाँ रहने के लिए है।


0

कारण यह है कि "बूल" जावा भाषा का हिस्सा "एनम" से बहुत पहले था। कई वर्षों के लिए, "बूल" बहुत ही वांछनीय था, जबकि "एनम" उपलब्ध नहीं था। केवल अब आप कह सकते हैं कि "यदि एनम शुरू से उपलब्ध था, तो हम एक अलग प्रकार के बजाय एनम के रूप में बूल को लागू कर सकते थे"।

स्विफ्ट में, जो "बूल" को एक एंम के रूप में व्यक्त कर सकता था, "ब्रील", "डार्विनबुलियन" और "ओबजबूल" नाम की तीन संरचनाएं हैं, जो "एक्सप्रेसबलबायबूलियनलिटरल" प्रोटोकॉल को लागू करती हैं। (डार्विनबुलियन एक C या C ++ बूल के अनुकूल है, ObjCBool ​​एक Objective-C BOO के लिए अनुकूल है)। "सत्य" और "असत्य" संकलक द्वारा पहचाने जाने वाले विशेष मूल्य हैं, और इसका उपयोग केवल "ExpressibleByBooleanLiteral" प्रोटोकॉल का समर्थन करने वाली वस्तुओं को इनिशियलाइज़ करने के लिए किया जा सकता है। बूल में एक आंतरिक चर "_value" होता है जिसमें एक बिट पूर्णांक होता है।

इसलिए बूल स्विफ्ट भाषा का हिस्सा नहीं है, बल्कि मानक पुस्तकालय का है। सही और गलत भाषा का हिस्सा हैं, और इसलिए ExpressibleByBooleanLiteral प्रोटोकॉल है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.