2011-03-05 18 views
77

मैं सोच रहा था क्या निम्नलिखित दो विधि घोषणाओं के बीच अंतर है बनाम:जावा जेनरिक टी वस्तु

public Object doSomething(Object obj) {....} 

public <T> T doSomething(T t) {....} 

वहाँ कुछ आप/एक के साथ क्या करना होगा कर सकते हैं लेकिन अन्य नहीं है? मुझे इस साइट पर कहीं और यह सवाल नहीं मिला।

उत्तर

65

संदर्भ से अलग - कोई अंतर नहीं। t और obj दोनों पर आप केवल Object के तरीकों का आह्वान कर सकते हैं।

लेकिन संदर्भ के साथ - आप एक सामान्य वर्ग अगर:

MyClass<Foo> my = new MyClass<Foo>(); 
Foo foo = new Foo(); 

तब:

Foo newFoo = my.doSomething(foo); 

वस्तु के साथ एक ही कोड

Foo newFoo = (Foo) my.doSomething(foo); 

दो फायदे:

  • कास्टिंग की कोई आवश्यकता नहीं है (संकलक इसे आप से छुपाता है)
  • काम करता है जो समय सुरक्षा संकलित करता है। यदि Object संस्करण का उपयोग किया जाता है, तो आप सुनिश्चित नहीं होंगे कि विधि हमेशा Foo लौटाती है। यदि यह Bar देता है, तो आपके पास रनटाइम पर ClassCastException होगा।
1

आपको अतिरिक्त कक्षा कास्टिंग करने की आवश्यकता नहीं है। पहले मामले में आपको हमेशा क्लास java.lang.Object का ऑब्जेक्ट प्राप्त होगा जिसे आपको अपनी कक्षा में डालने की आवश्यकता होगी। दूसरे मामले में टी को सामान्य हस्ताक्षर में परिभाषित कक्षा के साथ प्रतिस्थापित किया जाएगा और कोई वर्ग कास्टिंग की आवश्यकता नहीं होगी।

2

रनटाइम पर, कुछ भी नहीं। लेकिन संकलन समय पर दूसरा यह सुनिश्चित करने के लिए टाइप करेगा कि पैरामीटर का प्रकार और रिटर्न वैल्यू मैच (या उपप्रकारों के प्रकार) का प्रकार जो भी प्रकार टी को हल करता है (पहला उदाहरण भी टाइपिंग टाइप करता है लेकिन प्रत्येक ऑब्जेक्ट एक है ऑब्जेक्ट का उप प्रकार इसलिए हर प्रकार स्वीकार किया जाएगा)।

2

टी एक सामान्य प्रकार है। इसका अर्थ यह रनटाइम पर किसी भी योग्यता ऑब्जेक्ट द्वारा प्रतिस्थापित किया जा सकता है। इस प्रकार आप इस तरह के एक विधि आह्वान हो सकता है:

String response = doSomething("hello world");

या

MyObject response = doSomething(new MyObject());

या

Integer response = doSomething(31);

जैसा कि आप देख सकते हैं, वहाँ बहुरूपता यहाँ है।

लेकिन यदि ऑब्जेक्ट को वापस करने के लिए घोषित किया गया है, तो आप इसे तब तक नहीं कर सकते जब तक कि आप कास्ट चीजें टाइप न करें।

7

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

दूसरे में, लौटाया गया प्रकार उसी प्रकार के जैसा होगा जब कक्षा परिभाषित की गई थी।

Example ex = new Example<Integer>(); 

यहां हम निर्दिष्ट करते हैं कि टी किस प्रकार होगा जो हमें कक्षा या विधि पर अधिक बाधाओं को लागू करने की अनुमति देता है। उदाहरण के लिए हम LinkedList<Integer> या LinkedList<Example> को तुरंत चालू कर सकते हैं और हम जानते हैं कि जब हम इन तरीकों में से किसी एक को कॉल करते हैं, तो हम एक इंटीजर या उदाहरण उदाहरण वापस प्राप्त करेंगे।

यहां मुख्य लक्ष्य यह है कि कॉलिंग कोड यह निर्दिष्ट करने के लिए प्रकार-कास्टिंग पर भरोसा करने के बजाय, कक्षा किस प्रकार की वस्तुओं को संचालित करेगा, निर्दिष्ट कर सकता है।

ओरेकल से Java Generics * देखें।

* अद्यतन लिंक।

0

पहले मामले में यह किसी भी प्रकार का पैरामीटर लेता है egstring और एक प्रकार foo लौटाता है। दूसरे मामले में यह प्रकार foo का पैरामीटर लेता है और प्रकार foo का ऑब्जेक्ट देता है।

5

अंतर यह है कि सामान्य तरीकों के साथ मैं कास्ट करने के लिए की जरूरत नहीं है और मैं एक संकलन त्रुटि मिलती है जब मैं गलत करते हैं:

public class App { 

    public static void main(String[] args) { 

     String s = process("vv"); 
     String b = process(new Object()); // Compilation error 
    } 

    public static <T> T process(T val) { 

     return val; 
    } 
} 

वस्तु का उपयोग करते हुए मैं हमेशा कास्ट करने के लिए की जरूरत है और मैं किसी भी नहीं मिलता है त्रुटियां जब मैं गलत करता हूं:

public class App { 

    public static void main(String[] args) { 

     String s = (String)process("vv"); 
     String b = (String)process(new Object()); 
    } 

    public static Object process(Object val) { 

     return val; 
    } 
} 
संबंधित मुद्दे