2012-04-06 13 views
7

मेरे पास संकलन समय पर कक्षा का विस्तार करने की क्षमता है, लेकिन मुझे सुपरक्लास के उदाहरण का उपयोग करके रनटाइम पर इस सबक्लास का एक उदाहरण बनाने में सक्षम होना चाहिए जो पहले से ही तत्काल था।जावा: रनटाइम पर कक्षा बढ़ाना

यह सिद्धांत में संभव होना चाहिए क्योंकि सुपरक्लास निर्माता पहले से ही उप-वर्ग निर्माता से पहले बुलाए जाते हैं।

मेरे पास मेरे उप-वर्ग में तत्कालता को बदलने के लिए पर्याप्त रूप से प्रोग्राम तक पहुंच नहीं है और न ही मूल तत्कालता को बाधित करने के लिए।

केस का उपयोग करें: कक्षा X के उदाहरणों की एक मौजूदा सरणी है। मेरा कोड बाद में लोड हो गया है। मुझे अपने लोड किए गए सबक्लास वाई के साथ एक्स एक्स में से एक के तरीकों में से एक को ओवरराइड करने की आवश्यकता है। एक्स प्रोग्राम केवल उस सरणी के माध्यम से ऑब्जेक्ट्स तक पहुंचता है, इसलिए मैं अपने ए उदाहरण के साथ उस सरणी तत्व को प्रतिस्थापित करना चाहता हूं, लेकिन इसे करने की आवश्यकता है व्यवहार करें जैसे कि मूल रूप से उस सरणी में तत्काल किया गया था। मैं सिर्फ सुपरक्लस इंस्टेंस और आगे कॉल नहीं कर सकता, और सुपरक्लास को बहाल करने में मुश्किल जटिलताएं हैं।

मुझे उम्मीद है कि यह अधिक स्पष्ट है।

+3

कृपया प्रश्न को दोबारा लिखें। –

+1

क्या आप वास्तव में जो कुछ हासिल करने की कोशिश कर रहे हैं उसका एक उदाहरण भी प्रदान कर सकते हैं? बस वांछित, लेकिन संभवतः असंभव, ऐसा करने की विधि के बजाय। – millimoose

+0

मौजूदा लाइन मानें "सार्वजनिक स्थैतिक फू foo = नया फू();" कि मैं बदल नहीं सकता। मेरे पास "पब्लिक क्लास बार फू फैलाता है" और मैं "foo = new bar (...)" करना चाहता हूं जैसे कि यह पहली पंक्ति थी "सार्वजनिक स्थैतिक फू foo = new bar()"। – JAKJ

उत्तर

5

जो आप करने की कोशिश कर रहे हैं उसे दोहराने के लिए ..

जेवीएम के भीतर, क्लासए का एक उदाहरण मौजूद है। आप क्लासए के वर्ग विरासत को गतिशील रूप से संशोधित करना चाहते हैं, जैसे क्लास बी से क्लास बी नामक एक नई कक्षा मौजूद है। फिर आप क्लासबी के एक उदाहरण को तुरंत चालू करना चाहते हैं लेकिन क्लासए के मौजूदा उदाहरण की यह सबक्लास कार्यान्वयन है। स्मृति प्रतिस्थापन की तरह कुछ।

आप http://www.jboss.org/javassist पर देख सकते हैं। आपको क्लासलोडर को प्रतिस्थापित करने की आवश्यकता होगी, फिर यह निर्धारित करें कि कक्षाए कब लोड किया जा रहा है, फिर तत्काल। इसके बाद आपको क्लासबी बनाने और इसके बदले में वापस करने की आवश्यकता होगी।

अद्यतन

थोड़ा और अनुसंधान के बाद वहाँ अभी भी संभावना आप आप क्या चाहते हैं कर सकते हैं। आईडीईई की तरह ग्रहण समर्थन डीबगिंग के दौरान HotSwap'ing विधि कार्यान्वयन। वे इंस्ट्रुमेंटेशन एपीआई का उपयोग करते हैं।

http://zeroturnaround.com/blog/reloading_java_classes_401_hotswap_jrebel/

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

+0

मैं रनटाइम पर विरासत को नहीं बदल रहा हूं, लेकिन केवल सुपरक्लास को तत्काल चालू कर रहा हूं जब इसका सुपरक्लस पहले ही चालू हो चुका है। – JAKJ

+0

@JAKJ उत्तर अभी भी वही है। आपके पास एक मौजूदा ऑब्जेक्ट है जिसे आप किसी अन्य प्रकार की ऑब्जेक्ट में एडाप्टर करना चाहते हैं। यदि आप इस नए ऑब्जेक्ट के प्रारंभिक रिटर्न पॉइंट को नियंत्रित कर सकते हैं तो आप इसे एडाप्टर कर सकते हैं और जो इंस्टेंस चाहते हैं उसे वापस कर सकते हैं। मेरा सुझाव है कि आप अपने प्रयोग केस के साथ अपना प्रश्न अपडेट करें जो आपको लगता है कि समाधान क्या है। –

+0

मेरे पास क्लासलोडर को प्रतिस्थापित करने की क्षमता नहीं है क्योंकि मेरी कक्षा सुपरक्लास के बाद लोड की गई है और न ही मैं तृतीय-पक्ष रनटाइम का उपयोग कर सकता हूं। यह जावा के भीतर होना चाहिए। – JAKJ

1

क्या आपने जावा प्रॉक्सी को देखा है?

यहाँ जावाडोक से एक टुकड़ा है:

"एक गतिशील प्रॉक्सी वर्ग (बस नीचे दिए गए एक प्रॉक्सी वर्ग के रूप में जाना जाता है) एक वर्ग जो रनटाइम के दौरान निर्दिष्ट इंटरफेस की एक सूची को लागू करता है जब वर्ग बनाई गई है कि"
+0

ऐसा लगता है कि प्रॉक्सी इंटरफेस के लिए हैं, वर्ग नहीं। – JAKJ

3

मैं cglib उपयोग करने का सुझाव होगा:

cglib एक शक्तिशाली, उच्च प्रदर्शन और गुणवत्ता कोड जनरेशन लाइब्रेरी है, यह क्रम में जावा वर्गों का विस्तार करने के लिए प्रयोग किया जाता है और लागू करता है इंटरफेस

आप यहां कुछ उदाहरण मिल सकते हैं: https://github.com/cglib/cglib/wiki

2

मुझे नहीं पता कि यह एक सॉल्शन है लेकिन यदि आपके पास है

public static Foo foo = new Foo(); 

और आप बार जो फैली फू अपने बार उदाहरण के लिए foo बिंदु जाने के लिए फू और उपयोग प्रतिबिंब के लिए एक आवरण बार बनाने के साथ इसे बदलना चाहते।

public class Foo extends Bar { 
    private bar; 
    public Foo(Bar oldInstance) { 
    this.bar = oldInstance; 
    } 
} 

और

// exception handling ommitted 
public static void onStartup() { 
    Class fooRefClass = FooRef.class; 
    Field fooRef = fooRefClass.getDeclaredField("foo"); 

    Foo foo = (Foo)fooRef.get(null); 
    Bar bar = new Bar(foo); 
    fooRef.set(null, bar); 

}

के रूप में कहा कि अगर यह आपके मामले में संभव है मैं नहीं जानता।