2013-02-25 67 views
7

इंटरफेस में परिभाषित इंटरफ़ेस प्रभावी जावा जेनेरिक अध्याय पर विचार करें।इस अनचेक चेतावनी को दबाने के लिए सुरक्षित क्यों है?

public interface UnaryFunction<T> { 
T apply(T arg); 
} 

और UnaryFunction

// Generic singleton factory pattern 
private static UnaryFunction<Object> IDENTITY_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return arg; } 
}; 

// IDENTITY_FUNCTION is stateless and its type parameter is 
// unbounded so it's safe to share one instance across all types. 
@SuppressWarnings("unchecked") 
public static <T> UnaryFunction<T> identityFunction() { 
    return (UnaryFunction<T>) IDENTITY_FUNCTION; 
} 

लौटने क्यों है (UnaryFunction<T>) को IDENTITY_FUNCTION के कलाकारों सुरक्षित के लिए निम्न कोड?

पुस्तक यह सवाल पूछती है कि मैं पूछ रहा हूं लेकिन मैं यहां तर्क का पालन नहीं कर सकता। हम apply फ़ंक्शन का आविष्कार कर रहे हैं जो पहचान ऑपरेशन करता है? मैं उलझन में हूं क्योंकि यह वह कार्य है जो किसी भी वस्तु को संशोधित किए बिना उसी वस्तु को पार करता है।

(UnaryFunction<T>) को IDENTITY_FUNCTION के कलाकारों, एक अनियंत्रित डाली चेतावनी उत्पन्न करता है के रूप में UnaryFunction<Object> हर T के लिए एक UnaryFunction<T> नहीं है। लेकिन पहचान फ़ंक्शन विशेष है: इसके तर्क को अनमोडिफाइड देता है, इसलिए हम जानते हैं कि यह का उपयोग UnaryFunction<T> के रूप में T के मान के रूप में करने के लिए टाइपएफ़ है। इसलिए, हम आत्मविश्वास से अनचेक किए गए कास्ट चेतावनी को दबा सकते हैं जो द्वारा इस कलाकार द्वारा उत्पन्न किया गया है। एक बार ऐसा करने के बाद, कोड त्रुटि के बिना संकलित करता है या चेतावनी।

+0

साइड प्रश्न: क्या आप पुस्तक का उपयोग कर रहे हैं, और यह कहना है कि इस कोड की बात है? – asteri

+0

@Jeff प्रभावी जावा पुस्तक का नाम है और यह जेनरिक अध्याय में है, खंड है कि जेनेरिक कार्यों का वर्णन करता है में विशेष रूप से। – Geek

उत्तर

3

डाली पहचान फ़ंक्शन सटीक उद्देश्य यह है कि पहली जगह में इसे करने के लिए पारित किया गया था के रूप में ही इस कदर सुरक्षित है। ऐसे में, रनटाइम पर, जेनेरिक पैरामीटर T का कोई विशेषज्ञ नहीं है जो कास्ट का उल्लंघन कर सकता है।

उर्फ, आप ऑब्जेक्ट को अपने स्वयं के प्रकार के रूप में कास्टिंग कर रहे हैं।

3

प्रकार विलोपन

T apply(T arg); 

के साथ वास्तव में यह मान सकते हैं कि यह हमेशा सही है (y = x; के बराबर है) पहचान

Abc x = ...; 
Abc y = IDENTITY.apply(x); 

एक के लिए अब

Object apply(Object arg); 

है।

(बहुत व्यावहारिक।)

+0

कहाँ 'apply' प्रश्न में कोड में कहा जाता है? – Geek

+0

जब भी identityFunction लागू किया जाता है (.apply) परिणाम असाइन किया गया है टी IDENTITY.apply (टी), जो आम तौर पर, नहीं किया जा सकता के रूप में पैरामीटर के टी वहाँ कार्यावधि में नहीं है। –

1

पहचान फ़ंक्शन() अलग-अलग ऑब्जेक्ट्स पर उपयोग करने के लिए बस फ़ंक्शन को ही लौटाता है।

String result = identityFunction().apply("Hello"); 

प्रकार सुरक्षा चेतावनी महत्वपूर्ण है:

के बाद एक उपयोग उदाहरण है। ऐसा इसलिए है क्योंकि IDENTITY_FUNCTION को कार्यान्वित किया गया है कि संकलक गारंटी नहीं दे सकता कि फ़ंक्शन इनपुट के समान प्रकार देता है। निम्नलिखित वैकल्पिक कार्यान्वयन पर विचार करें:

private static UnaryFunction<Object> CONST_FUNCTION = new UnaryFunction<Object>() { 
    public Object apply(Object arg) { return "Default"; } 
}; 

इस कार्यान्वयन हमेशा एक स्ट्रिंग देता है, तो यह स्पष्ट रूप से सुरक्षित एक सामान्य डेटा प्रकार पर एक एकल समारोह के रूप में यह वापस जाने के लिए नहीं है।

हमारे मामले (IDENTITY_FUNCTION) में, सबूत है कि लौटे प्रकार इनपुट प्रकार के समान ही है कार्यान्वयन के अंदर है। हम एक ही उदाहरण वापस करते हैं, इसलिए यह एक ही प्रकार की गारंटी है। जब आप सुरक्षा चेतावनियों को दबाते हैं, तो इसे प्रमाण के साथ उचित ठहराने की अनुशंसा की जाती है।

+0

-1 उलझन में। पहचान फ़ंक्शन() "फ़ंक्शन स्वयं" वापस नहीं करता है, यह _argument_ स्वयं लौटाता है। मुझे कोई कारण नहीं दिखता कि इस परिणाम का प्रकार टी टाइप करने के लिए "विभिन्न वस्तुओं पर इस्तेमाल किया जाना" है। आपके उदाहरण में, यह एक स्ट्रिंग है जो विभिन्न वस्तुओं पर _cannot_ _used_ हो। – user949300

+1

user949300 @: 'identityFunction()' वस्तु चर 'IDENTITY_FUNCTION' में संग्रहीत के लिए एक संदर्भ देता है। वह संदर्भ आपको 'लागू() 'पर कॉल करने की अनुमति देता है, इस प्रकार' पहचान समारोह() 'प्रभावी ढंग से कार्य को वापस कर देता है। यदि नाम समान नहीं थे तो यह बेहतर होता। पूर्व 'getIdentityFunction() 'और' IDENTITY_FUNCTION' प्राप्त करें। उत्तर की पहली पंक्ति गेटटर विधि का जिक्र कर रही है। – unholysampler

+0

धन्यवाद - समझा। यह पूरा प्रश्न/प्रणाली कुछ ऐसी चीज के लिए बहुत भ्रमित है जो कुछ भी नहीं करता है :-)। जब तक आप StackOverflow में सीमाओं के कारण अपना उत्तर संपादित नहीं करते हैं, तब तक मैं अपने डाउनवोट को "पूर्ववत नहीं कर सकता"। – user949300