2008-09-09 3 views
24

मान लें कि मेरे पास निम्न वर्ग है:जावा जेनिक्स: ऑब्जेक्ट ओ की श्रेणी <E> से तुलना करना

public class Test<E> { 
    public boolean sameClassAs(Object o) { 
     // TODO help! 
    } 
} 

मैं कैसे जांचूँगा कि oE के समान वर्ग है?

Test<String> test = new Test<String>(); 
test.sameClassAs("a string"); // returns true; 
test.sameClassAs(4); // returns false; 

मैं (Object o) से विधि हस्ताक्षर नहीं बदल सकता क्योंकि मैं एक सुपरक्लास को ओवरराइड कर रहा हूं और इसलिए मेरी विधि हस्ताक्षर चुनने के लिए नहीं मिलता है।

मैं एक कलाकार का प्रयास करने की सड़क पर भी नहीं जाऊंगा और फिर परिणामस्वरूप अपवाद को पकड़ने में विफल रहता हूं।

उत्तर

26

Test का एक उदाहरण क्या E रनटाइम पर है के रूप में कोई जानकारी नहीं है। तो, आपको टेस्ट के निर्माता को Class<E> पास करने की आवश्यकता है।

public class Test<E> { 
    private final Class<E> clazz; 
    public Test(Class<E> clazz) { 
     if (clazz == null) { 
      throw new NullPointerException(); 
     } 
     this.clazz = clazz; 
    } 
    // To make things easier on clients: 
    public static <T> Test<T> create(Class<T> clazz) { 
     return new Test<T>(clazz); 
    } 
    public boolean sameClassAs(Object o) { 
     return o != null && o.getClass() == clazz; 
    } 
} 

आप एक "instanceof" संबंध चाहते हैं, बजाय Class तुलना की Class.isAssignableFrom का उपयोग करें। नोट, E को गैर-जेनेरिक प्रकार होने की आवश्यकता होगी, उसी कारण से Test को Class ऑब्जेक्ट की आवश्यकता है।

जावा एपीआई में उदाहरणों के लिए, java.util.Collections.checkedSet और इसी तरह देखें।

+1

मैं नहीं बल्कि बराबरी के साथ वर्गों की तुलना चाहते हैं:

तो अपने sameClassAs विधि की तरह दिखना चाहिए। या == का उपयोग करने के लिए एक विशेष कारण है? – ordnungswidrig

+1

वे समकक्ष हैं। आईएमओ == पढ़ने के लिए आसान है (हालांकि इसका मतलब यह है कि पाठक को इस प्रकार के बारे में पता होना चाहिए)। इनलाइनिंग से पहले यह आंशिक रूप से तेज़ है। अब, जो मैंने परीक्षण नहीं किया है वह एक नल क्लैज है। –

2

मैं केवल इसे इस तरह से काम कर रहा हो सकता है:

public class Test<E> { 

    private E e; 

    public void setE(E e) { 
     this.e = e; 
    } 

    public boolean sameClassAs(Object o) { 

     return (o.getClass().equals(e.getClass())); 
    } 

    public boolean sameClassAs2(Object o) { 
     return e.getClass().isInstance(o); 
    } 
} 
9

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

public class Test<E> { 
    private Class<E> clazz; 
    public Test(Class<E> clazz) { 
     this.clazz = clazz; 
    } 
    public boolean sameClassAs(Object o) { 
     return this.clazz.isInstance(o); 
    } 
} 
-1

मैं बस वही काम करने की कोशिश कर रहा था, और एक साफ चाल मैंने महसूस किया कि आप एक कास्ट की कोशिश कर सकते हैं, और यदि कास्ट विफल हो जाता है, तो क्लासकास्ट अपवाद फेंक दिया जाएगा। आप इसे पकड़ सकते हैं, और जो कुछ भी कर सकते हैं।

public boolean sameClassAs(Object o) { 
    boolean same = false; 
    try { 
     E t = (E)o; 
     same = true; 
    } catch (ClassCastException e) { 
     // same is false, nothing else to do 
    } finally { 
     return same; 
    } 
} 
+3

नहीं, यह नहीं होगा। यह एक अनचेक कास्ट है। यह कभी अपवाद नहीं फेंक देगा। रनटाइम पर, "टी" में ई के क्षरण का प्रकार होता है, जो कि ऑब्जेक्ट है, इसलिए कोई कलाकार नहीं किया जाता है। – newacct

+0

आप सही हैं। इससे मुझे बाद में कई समस्या निवारण बचाएंगे, क्योंकि संकलन ठीक लगता है। – Ayman

संबंधित मुद्दे