2010-04-30 17 views
6

सरल सवाल, लेकिन मुझे लगता है कि मुश्किल जवाब।जावा जेनेरिक इंटरफेस प्रदर्शन

जेनेरिक इंटरफेस का उपयोग प्रदर्शन को नुकसान पहुंचाता है?

उदाहरण:

public interface Stuff<T> { 

    void hello(T var); 
} 

vs 

public interface Stuff { 

    void hello(Integer var); <---- Integer used just as an example 
} 

मेरी पहली सोचा कि यदि ऐसा नहीं होता है। जेनेरिक भाषा का हिस्सा हैं और संकलक इसे अनुकूलित करेंगे जैसे कि कोई जेनरिक नहीं था (कम से कम जेनेरिक इंटरफेस के इस विशेष मामले में)।

क्या यह सही है?

+1

जहां तक ​​मैं देख सकता हूं, वे सीधे तुलनीय नहीं हैं। दूसरे उदाहरण को 'ऑब्जेक्ट' को पैरामीटर के रूप में नहीं लेना चाहिए? –

उत्तर

10

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

public class GenericPerformance { 
    public static void main(final String[] args) { 
     final Stuff<Integer> stuff = new IntStuff(); 
     final Integer data = stuff.getData(); 
     stuff.putData(data); 
    } 
} 

interface Stuff<T> { 
    T getData(); 
    void putData(T stuff); 
} 

class IntStuff implements Stuff<Integer> { 
    private Integer stuff; 
    public Integer getData() { 
     return stuff; 
    } 
    public void putData(final Integer stuff) { 
     this.stuff = stuff; 
    } 
} 

आप उत्पन्न बाईटकोड को देखें, तो आप देखेंगे: मुख्य विधि में, मिट इंटरफ़ेस तरीकों

java.lang.Object Stuff.getData() 
void Stuff.putData(java.lang.Object) 

लागू कर रहे हैं। विधियों, हस्ताक्षर

java.lang.Object getData() 
void putData(java.lang.Object) 
संशोधक public bridge synthetic साथ

दोनों के साथ IntStuff में लागू, "असली" तरीकों

java.lang.Integer IntStuff.getData() 
void putData(java.lang.Integer) 

पहले कृत्रिम विधि केवल पूर्णांक परिणाम देता प्रतिनिधि यही कारण है कि, जबकि दूसरा प्रदर्शन putData(Integer) पर कॉल करने से पहले ऑब्जेक्ट से इंटीजर तक कास्ट।

आप टाइप करने के लिए IntStuffstuff चर बदलते हैं, तो दोनों Integer तरीकों के बजाय सिंथेटिक Object तरीकों में से कहा जाता है।

+1

+1, मुझे इसे हराया, सिंथेटिक तरीके ओवरहेड जोड़ते हैं - हालांकि यह एक माइक्रो-ऑप्टिमाइज़ेशन है कि जेआईटी किसी भी तरह से ऑप्टिमाइज़ करने की संभावना है, इसलिए किसी को भी तब तक परवाह नहीं करनी चाहिए जब तक कोई समस्या वास्तव में प्रस्तुत न हो। लेकिन मामले में जानना उपयोगी है। – Yishai

+2

आप सही हैं। आम तौर पर, ओवरहेड जेनिक्स से बचने के प्रयास के लायक नहीं है। लेकिन ऐसा लगता है कि जेआईटी पुल विधि को पूरी तरह अनुकूलित नहीं कर सकता है। मैंने अभी एक लूप के साथ कुछ परीक्षण किए हैं जिनमें केवल 'अंतिम इंटीजर डेटा = intstuff.getData() है; intstuff.putData (डेटा); '। 'स्टफ स्टफ' वैरिएबल के साथ लूप को चलाने से 'इंस्टफफ सामग्री' चर के साथ 30% अधिक समय की आवश्यकता होती है, यहां तक ​​कि '-सर्वर' JVM विकल्प के साथ भी। –

7

युप - जावा जेनरिक एक पूरी तरह से संकलित समय निर्माण है। JVM इसे एक सामान्य इंटरफ़ेस के रूप में देखता है। तो जेनेरिक का उपयोग कर कोई रनटाइम प्रदर्शन लाभ या हानि नहीं है।

4

वे टाइप सुरक्षा के लिए संकलन-समय पर बस एक सहायक हैं।

जेनिक्स टाइप एरर द्वारा कार्यान्वित किए जाते हैं: सामान्य प्रकार की जानकारी केवल संकलन समय पर मौजूद होती है, जिसके बाद इसे कंपाइलर द्वारा मिटा दिया जाता है।

से लिया: http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html

1

वास्तव में, मुझे विश्वास है कि वहाँ अपने उदाहरण में है एक छोटा सा प्रदर्शन अंतर। पहले संस्करण का संकलित रूप मानता है कि हैलो() को ऑब्जेक्ट प्राप्त होता है, जबकि दूसरे में यह एक इंटीजर मानता है। इसलिए, जब आप StuffImpl < इंटीजर> को तुरंत चालू करते हैं, तो संकलक द्वारा जोड़े गए निहित कलाकार के कारण हैलो() पर कॉल थोड़ा धीमा हो जाएगा।

- सुधार -

निहित डाली नमस्ते करने के लिए नहीं जोड़ा जाएगा()। हालांकि, यदि आप टी प्राप्त करने वाले गेटर विधि को जोड़ते हैं, तो कलाकार को लौटाए गए मूल्य में जोड़ा जाएगा।

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

+0

'सामग्री ' के किसी भी ठोस कार्यान्वयन के लिए, उदा। टी को 'इंटीगर' के रूप में, 'ऑब्जेक्ट' से कंक्रीट प्रकार, 'इंटेगर' तक एक निहित कास्ट दिया जाएगा। विवरण के लिए मेरा जवाब देखें। –

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