2008-11-14 10 views
27

विधि वर्ग के नेविगेशन के दौरान मैं समारोह में आया था ब्रिज(), जिसमें जावाडोक कहता है, यह सच है कि जावा स्पेक विधि को यथासंभव घोषित करता है।क्या java.lang.reflect.Method.is ब्रिज() के लिए उपयोग किया जाता है?

कृपया मुझे यह समझने में सहायता करें कि इसका क्या उपयोग किया जाता है? क्या एक कस्टम वर्ग यदि आवश्यक हो तो पुल के रूप में अपनी विधि घोषित कर सकता है?

उत्तर

27

पैरामीटरयुक्त प्रकार को विस्तारित करते समय संकलक द्वारा एक पुल विधि बनाई जा सकती है जिसके तरीकों ने तर्कों को पैरामीटर किया है।

आप इस कक्षा BridgeMethodResolver में 'पुल विधि' द्वारा संदर्भित वास्तविक विधि प्राप्त करने के लिए एक तरीका खोज सकते हैं।

Create Frame, Synchronize, Transfer Control देखें:

ऐसी स्थिति का एक उदाहरण के रूप में, घोषणाओं पर विचार करें:

class C<T> { abstract T id(T x); } 
class D extends C<String> { String id(String x) { return x; } } 

अब, एक मंगलाचरण

C c = new D(); 
c.id(new Object()); // fails with a ClassCastException 

वास्तविक विधि का विलोपन लागू किया जा रहा दी , D.id(String) संकलन-समय विधि घोषणा, C.id(Object) के हस्ताक्षर में भिन्न है। पूर्व स्ट्रिंग प्रकार का तर्क लेता है जबकि उत्तरार्द्ध प्रकार ऑब्जेक्ट का तर्क लेता है। विधि के निष्पादन से पहले आमंत्रण क्लासकास्ट अपवाद के साथ विफल रहता है।

ऐसी स्थितियां केवल तब उत्पन्न हो सकती हैं जब प्रोग्राम एक अनचेक चेतावनी (§5.1.9) को जन्म देता है।

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

Object id(Object x) { return id((String) x); } 

इस विधि है कि वास्तव में कॉल c.id(new Object()) ऊपर दिखाए गए के जवाब में जावा आभासी मशीन द्वारा लागू किया जा जाएगा है, और यह निष्पादित करेंगे आवश्यकतानुसार कास्ट और असफल।

भी Bridge देखें:

के रूप में टिप्पणी में उल्लेख किया है, पुल तरीकों में भी covariant अधिभावी के लिए आवश्यक हैं:

  • जावा 1.4, में और इससे पहले, एक विधि है, तो एक और ओवरराइड कर सकते हैं हस्ताक्षर मिलान बिल्कुल।
  • जावा 5 में, एक विधि है, तो तर्क बिल्कुल से मेल खाते हैं लेकिन वापसी प्रकार अधिभावी विधि के, अगर यह अन्य विधि की वापसी प्रकार का एक उप प्रकार है एक और ओवरराइड कर सकते हैं।

आमतौर पर, एक विधि Object clone() एक MyObject clone() द्वारा अधिरोहित जा सकता है, लेकिन एक पुल विधि संकलक द्वारा उत्पन्न हो जाएगा:

public bridge Object MyObject.clone(); 
+2

जेनरिक के बिना भी, कॉन्वेंट रिटर्न प्रकारों के लिए ब्रिज विधियां आवश्यक हैं। –

+0

BridgeMethodResolver लिंक टूटा हुआ है :( – BrunoJCM

+0

@ ब्रूनोजेसीएम अच्छा पकड़। मैंने लिंक को पुनर्स्थापित कर दिया है (कक्षा को परियोजना 'org.springframework.core' से' स्प्रिंग-फ्रेमवर्क 'प्रोजेक्ट में स्थानांतरित कर दिया गया है: https://fisheye.springsource.org /browse/spring-framework/org.springframework.core/src/main/java/org/springframework/core/BridgeMethodResolver.java#rdc41daa3db350ef9a4b14ef1d750d79cb22cf431) – VonC

3

उदाहरण वहाँ से पता चला (JLS से उद्धृत) यह की तरह ध्वनि बनाता है पुल विधियों का उपयोग केवल उन परिस्थितियों में किया जाता है जहां कच्चे प्रकार का उपयोग किया जाता है।चूंकि यह मामला नहीं है, मैंने सोचा कि मैं एक उदाहरण के साथ पाइप करूंगा जहां पुल विधियों का उपयोग पूरी तरह से टाइप-सही जेनेरिक कोड के लिए किया जाता है।

public static interface Function<A,R> { 
    public R apply (A arg); 
} 
public static <A, R> R applyFunc (Function<A,R> func, A arg) { 
    return func.apply(arg); 
} 

आप निम्नलिखित तरीके से इस कोड का उपयोग करते हैं, तो एक पुल विधि का इस्तेमाल किया जाता है::

निम्नलिखित इंटरफेस और समारोह पर विचार करें

Function<String, String> lower = new Function<String, String>() { 
    public String apply (String arg) { 
     return arg.toLowerCase(); 
    } 
}; 
applyFunc(lower, "Hello"); 

विलोपन के बाद, Function इंटरफ़ेस विधि शामिल apply(Object)Object (जिसे आप बाइटकोड को डीकंपलिंग करके पुष्टि कर सकते हैं)। स्वाभाविक रूप से, यदि आप applyFunc के लिए डिकंपिल्ड कोड देखते हैं तो आप देखेंगे कि इसमें apply(Object)Object पर कॉल है। Object अपने प्रकार चर के ऊपरी बाउंड है, इसलिए कोई अन्य हस्ताक्षर समझ में नहीं आता है।

तो जबविधि के साथ एक अज्ञात वर्ग बनाया गया है, तो यह वास्तव में Function इंटरफ़ेस को लागू नहीं करता है जब तक कोई पुल विधि नहीं बनाई जाती। पुल विधि सभी सामान्य रूप से टाइप किए गए कोड को Function कार्यान्वयन का उपयोग करने की अनुमति देती है।

दिलचस्प है, केवल तभी वर्ग हस्ताक्षर apply(String)String और के साथ कुछ अन्य इंटरफ़ेस कार्यान्वित ही अगर विधि है कि इंटरफ़ेस प्रकार की एक संदर्भ के माध्यम से बुलाया गया था संकलक कभी कि हस्ताक्षर के साथ एक फोन का उत्सर्जन होता है।

यहां तक ​​कि अगर मैं निम्नलिखित कोड है:

Function<String, String> lower = ...; 
lower.apply("Hello"); 

संकलक अभी भी apply(Object)Object के लिए एक कॉल उत्सर्जन करता है।

वास्तव संकलक apply(String)String कॉल करने के लिए प्राप्त करने के लिए एक अन्य तरीका है, लेकिन यह एक गुमनाम वर्ग निर्माण अभिव्यक्ति करने के लिए सौंपा जादुई प्रकार है जो अन्यथा नीचे लिखा नहीं किया जा सकता का लाभ लेता है:

new Function<String, String>() { 
    public String apply (String arg) { 
     return arg.toLowerCase(); 
    } 
}.apply("Hello"); 
0

एक और मामला मैं जेनरेट के साथ कुछ भी नहीं है:

protected abstract class Super { 
    public void m() {} 
} 
public class Sub extends Super {} 
assert Sub.class.getMethod("m").isBridge(); 
संबंधित मुद्दे