Instof Vs getClass ()


114

जब मैं ऑपरेटर के उपयोग getClass()और ==परिचालक के रूप में प्रदर्शन में लाभ देखता हूँ instanceOf

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

क्या कोई दिशानिर्देश है, जिसका उपयोग करना है getClass()या instanceOf?

एक परिदृश्य को देखते हुए: मुझे पता है कि मिलान करने के लिए सटीक कक्षाएं हैं, अर्थात String, Integer(ये अंतिम कक्षाएं हैं), आदि।

क्या instanceOfऑपरेटर बुरा अभ्यास कर रहा है?


3
इसमें समझाया गया है: stackoverflow.com/questions/596462/…
क्लेमेंट पी

2
आपकी समय पद्धति कृत्रिम विलंब का कारण बन रही है और गलत समय परिणाम उत्पन्न कर रही है। आप जो चेक करते हैं, उस क्रम को स्वैप करें और आप देखेंगे कि पहला चेक जो आप करते हैं (या तो == या इंस्टाफ़ॉफ़) हमेशा लंबा रहेगा। मुझे लगता है कि यह प्रिंटल () का है। आपको उस सामान को अपने टाइमिंग ब्लॉक में कभी शामिल नहीं करना चाहिए।
कुर्तजमार्च

केवल एक टिप्पणी के अलावा, प्रदर्शन की तुलना करने के लिए, सटीकता में सुधार के लिए कई चक्र पुनरावृत्तियों (जैसे 10000) का उपयोग करें। एक एकल आह्वान एक अच्छा उपाय नहीं है।
martins.tuga

जवाबों:


140

कारण यह है कि के प्रदर्शन instanceofऔर getClass() == ...अलग है कि वे अलग अलग बातें कर रहे हैं।

  • instanceofपरीक्षण करता है कि क्या बाएं हाथ की ओर (एलएचएस) पर वस्तु का संदर्भ दाएं हाथ की तरफ (आरएचएस) या कुछ उपप्रकार के प्रकार का एक उदाहरण है ।

  • getClass() == ... परीक्षण कि क्या प्रकार समान हैं।

इसलिए सिफारिश प्रदर्शन के मुद्दे को नजरअंदाज करने और उस विकल्प का उपयोग करने की है जो आपको वह उत्तर देता है जिसकी आपको आवश्यकता है।

क्या instanceOfऑपरेटर खराब अभ्यास का उपयोग कर रहा है?

जरुरी नहीं। instanceOfया तो अति प्रयोग या "डिजाइन गंध" getClass() हो सकता है । यदि आप सावधान नहीं हैं, तो आप एक डिजाइन के साथ समाप्त होते हैं जहां नए उपवर्गों के अलावा कोड के एक महत्वपूर्ण मात्रा में परिणाम होता है। ज्यादातर स्थितियों में, पसंदीदा दृष्टिकोण बहुरूपता का उपयोग करना है।

हालांकि, ऐसे मामले हैं जहां ये "डिज़ाइन गंध" नहीं हैं। उदाहरण के लिए, equals(Object)आपको वास्तविक प्रकार के तर्क का परीक्षण करने की आवश्यकता है, और falseयदि यह मेल नहीं खाता है तो वापस लौटें । यह सबसे अच्छा उपयोग किया जाता है getClass()


"बेस्ट प्रैक्टिस", "बैड प्रैक्टिस", "डिज़ाइन स्मेल", "एंटीपैटर्न" और इस तरह की शर्तों को संयम से इस्तेमाल किया जाना चाहिए और संदेह के साथ इलाज किया जाना चाहिए। वे श्वेत-श्याम सोच को प्रोत्साहित करते हैं। यह पूरी तरह से हठधर्मिता पर आधारित होने के बजाय अपने निर्णय लेने के संदर्भ में बेहतर है; उदाहरण के लिए, किसी ने जो कहा वह "सर्वोत्तम अभ्यास" है।


@StephenC जैसा कि आपने कहा, यह code smellया तो उपयोग करना है । इसका मतलब है, यह खराब डिज़ाइन (गैर-बहुरूपी) कोड का परिणाम है जो आपको या तो उपयोग करने के लिए मिलता है। मैं इस तरह से उनमें से किसी का उपयोग कर सकते हैं?
ओवरएक्सचेंज

@overexchange - 1) मैंने कहा "अति प्रयोग" "उपयोग नहीं"। 2) इसके अलावा, मुझे समझ नहीं आ रहा है कि आप क्या पूछ रहे हैं। "अनुमान लगाओ ..." से आपका क्या मतलब है ??? कोड या तो इन चीजों का उपयोग करता है, या यह नहीं करता है।
स्टीफन सी

मुझे लगता है कि, कोड के मौजूदा ख़राब डिज़ाइन (गैर-बहुरूपी) के कारण चित्र का उपयोग instanceofऔर getClass()चित्र में आता है। क्या मैं सही हूँ?
ओवरएक्सचेंज

5
@overexchange - आप वैध रूप से अनुमान नहीं लगा सकते हैं कि instanceof(उदाहरण के लिए) सभी उपयोग खराब डिज़ाइन है। ऐसी परिस्थितियां हैं जहां यह सबसे अच्छा समाधान हो सकता है। उसी के लिए getClass()। मैं दोहराऊंगा कि मैंने कहा "अति प्रयोग" और "उपयोग" नहीं । हर मामले को उसकी खूबियों पर आंका जाना चाहिए ... न कि आँख बंद करके कुछ गैर-स्थापित हठधर्मी शासन लागू करने से।
स्टीफन सी

44

क्या आप किसी वर्ग से बिल्कुल मेल खाना चाहते हैं , जैसे FileInputStreamकिसी उपवर्ग के बजाय केवल मिलान FileInputStream? यदि हां, तो उपयोग करें getClass()और ==। मैं आमतौर पर ऐसा करता हूं equals, ताकि एक्स का एक उदाहरण एक्स के एक उपवर्ग के उदाहरण के बराबर नहीं माना जाता है - अन्यथा आप मुश्किल समरूपता समस्याओं में पड़ सकते हैं। दूसरी ओर, यह आमतौर पर तुलना करने के लिए अधिक उपयोगी है कि दो वस्तुएं एक विशिष्ट वर्ग की तुलना में एक ही वर्ग की हैं।

अन्यथा, उपयोग करें instanceof। ध्यान दें कि getClass()आपको यह सुनिश्चित करने की आवश्यकता होगी कि आपके पास शुरू करने के लिए एक गैर-शून्य संदर्भ है, या आपको ए मिलेगा NullPointerException, जबकि पहला ऑपरंड शून्य होने पर instanceofवापस आ जाएगा false

व्यक्तिगत तौर पर मैं कहना चाहता हूँ instanceofलेकिन का उपयोग कर - अधिक मुहावरेदार है या तो उनमें से बड़े पैमाने पर ज्यादातर मामलों में एक डिजाइन गंध है।


18

मुझे पता है कि यह पूछे जाने के बाद से कुछ समय हो गया है, लेकिन मैंने कल एक विकल्प सीखा

हम सभी जानते हैं कि आप क्या कर सकते हैं:

if(o instanceof String) {   // etc

लेकिन क्या होगा यदि आप नहीं जानते कि यह किस प्रकार का वर्ग होना चाहिए? आप उदारता से नहीं कर सकते:

if(o instanceof <Class variable>.getClass()) {   

जैसा कि यह एक संकलित त्रुटि देता है।
इसके बजाय, यहाँ एक विकल्प है - isAignignableFrom ()

उदाहरण के लिए:

public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {

    return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
}

8
उपयोग न करें isAssignableFrom। लिखने का सही तरीकाo instanceof Stringप्रतिबिंब का उपयोग करके का है String.getClass().isInstance(o)। जावदोक यहां तक ​​कहता है: यह विधि जावा भाषा instanceofऑपरेटर के गतिशील समकक्ष है ।
एंड्रियास

3

getClass () में यह प्रतिबंध है कि वस्तुएं केवल उसी वर्ग की अन्य वस्तुओं के बराबर हैं, समान समय प्रकार, जैसा कि नीचे दिए गए कोड के आउटपुट में चित्रित किया गया है:

class ParentClass{
}
public class SubClass extends ParentClass{
    public static void main(String []args){
        ParentClass parentClassInstance = new ParentClass();
        SubClass subClassInstance = new SubClass();
        if(subClassInstance instanceof ParentClass){
            System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
        }
        if(subClassInstance.getClass() != parentClassInstance.getClass()){
            System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
        }
    }
}

आउटपुट:

सबक्लास पेरेंटक्लास का विस्तार करता है। subClassInstance है Instof ParentClass।

अलग-अलग getClass () सब-क्लैसइन्स्टैन्स और पैरेंटक्लासइन्स्टैन्स के साथ रिटर्न परिणाम।

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