यह एक बहुत ही जटिल उत्तर के साथ एक बहुत ही सरल सवाल है। कृपया मुझे इसके साथ सहन करें क्योंकि मैं इसे समझाने की कोशिश करता हूं।
(मुझे यकीन है कि क्यों अपने स्टैक ट्रेस Class
में लाइन नंबर नहीं दे करता है नहीं कर रहा हूँ) स्रोत कोड जहां अपवाद Class
में उठाया है को देखते हुए:
try
{
Class[] empty = {};
final Constructor<T> c = getConstructor0(empty, Member.DECLARED);
// removed some code that was not relevant
}
catch (NoSuchMethodException e)
{
throw new InstantiationException(getName());
}
आप देखते हैं कि NoSuchMethodException
किया जा रहा है InstantiationException
के रूप में पुनर्स्थापित। इसका मतलब है कि कक्षा प्रकार object2
के लिए कोई गैर-तर्क निर्माता नहीं है।
पहला, object2
किस प्रकार का है? कोड
System.out.println("object2 class: " + object2.getClass());
के साथ हम देखते हैं कि
object2 वर्ग: कक्षा junk.NewMain $ 1
जो सही है (मैं, पैकेज कबाड़ में नमूना कोड को चलाने के वर्ग NewMain)।
junk.NewMain$1
के निर्माता क्या हैं?
Class obj2Class = object2.getClass();
try
{
Constructor[] ctors = obj2Class.getDeclaredConstructors();
for (Constructor cc : ctors)
{
System.out.println("my ctor is " + cc.toString());
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
जो हमें
मेरी ctor देता है $ 1 (java.util.Calendar) junk.NewMain है
तो अपने गुमनाम वर्ग एक Calendar
की तलाश में है में पारित किया जाना है। यह आपके लिए काम करेगा:
Object newObj = ctors[0].newInstance(Calendar.getInstance());
यदि आपके पास कुछ पसंद है ई इस:
final String finalString = "I'm final :)";
final Integer finalInteger = new Integer(30);
final Calendar calendar = Calendar.getInstance();
Object object2 = new Object()
{
{
System.out.println("Instance initializing block");
System.out.println(finalString);
System.out.println("My integer is " + finalInteger);
System.out.println(calendar.getTime().toString());
}
private void hiddenMethod()
{
System.out.println("Use reflection to find me :)");
}
};
तो newInstance
करने के लिए अपने कॉल क्योंकि वहाँ, ctor में पर्याप्त तर्क नहीं हैं, क्योंकि अब यह चाहता है काम नहीं करेगा:
मेरी ctor junk.NewMain $ 1 (जावा है। lang.Integer, java.util.Calendar)
मैं तो दृष्टांत तो उस के साथ
Object newObj = ctors[0].newInstance(new Integer(25), Calendar.getInstance());
डीबगर का उपयोग करने के अंदर एक झलक दिखाता है कि finalInteger
25 है और अंतिम मान 30 नहीं है।
चीजें थोड़ा जटिल हैं क्योंकि आप उपरोक्त सभी को एक स्थिर संदर्भ में कर रहे हैं। आप ऊपर अपने सभी कोड लेने के लिए और एक गैर स्थैतिक विधि में यह इतना की तरह ले जाते हैं (याद रखें, मेरी कक्षा junk.NewMain है):
public static void main(String[] args)
{
NewMain nm = new NewMain();
nm.doIt();
}
public void doIt()
{
final String finalString = "I'm final :)";
// etc etc
}
आप अपने भीतर के वर्ग के लिए ctor मिल जाएगा अब है (को हटाने मेरी जोड़ा पूर्णांक संदर्भ):
मेरी ctor junk.NewMain $ 1 है (junk.NewMain, java.util.Calendar)
Java Language Specification, खंड 15.9.3 यह इस तरह से बताते हैं:
तो सी एक अनाम वर्ग, और सी, एस के प्रत्यक्ष सुपर क्लास है, है एक भीतरी वर्ग है, तो: एस एक स्थानीय वर्ग है और एस एक स्थिर संदर्भ में होता है तो
- हैं तर्क सूची में तर्क, यदि कोई हो, तो अभिव्यक्ति में दिखाई देने वाले क्रम में कन्स्ट्रक्टर के लिए तर्क हैं।
- अन्यथा, तुरंत enclosing एस के संबंध में मैं के कहने निर्माता को पहले तर्क, वर्ग उदाहरण निर्माण अभिव्यक्ति की तर्क सूची में तर्क के बाद, यदि कोई हो, ताकि वे में प्रदर्शित में है भाव।
गुमनाम निर्माता सब पर बहस क्यों लगता है?
चूंकि आप किसी अज्ञात आंतरिक कक्षा के लिए कोई कन्स्ट्रक्टर नहीं बना सकते हैं, उदाहरण प्रारंभकर्ता ब्लॉक उस उद्देश्य को पूरा करता है (याद रखें, आपके पास केवल उस अज्ञात आंतरिक वर्ग का एक उदाहरण है)। वीएम को आंतरिक वर्ग का कोई ज्ञान नहीं है क्योंकि संकलक व्यक्तिगत वर्गों के रूप में सबकुछ अलग करता है (उदाहरण के लिए जंक। न्यूमैन $ 1)। उस वर्ग के लिए ctor उदाहरण प्रारंभकर्ता की सामग्री शामिल है।
यह JLS 15.9.5.1 Anonymous Constructors द्वारा explayed है:
... अनाम निर्माता वर्ग उदाहरण निर्माण अभिव्यक्ति है जिसमें सी घोषित है करने के लिए प्रत्येक वास्तविक तर्क के लिए एक औपचारिक पैरामीटर है।
आपके इंस्टेंस प्रारंभकर्ता के पास Calendar
ऑब्जेक्ट का संदर्भ है। कंपाइलर को उस आंतरिक समय में उस रनटाइम मान को और कैसे प्राप्त किया जा सकता है (जिसे केवल वीएम के लिए एक वर्ग के रूप में बनाया गया है) कन्स्ट्रक्टर के माध्यम से छोड़कर?
अंत में (यय), अंतिम जलने वाले प्रश्न का उत्तर। कन्स्ट्रक्टर को String
क्यों नहीं चाहिए? JLS 3.10.5 के अंतिम बिट बताते हैं कि:
स्ट्रिंग्स निरंतर भाव द्वारा गणना संकलन समय पर गणना की जाती है और फिर इलाज किया रूप में यदि वे शाब्दिक थे।
दूसरे शब्दों में, अपने String
मूल्य संकलन समय पर जाना जाता है, क्योंकि यह तो यह गुमनाम निर्माता का हिस्सा बनने की जरूरत नहीं है एक शाब्दिक है है। साबित करने के लिए यह मामला है हम JLS 3.10.5 में अगले बयान परीक्षण करेंगे:
स्ट्रिंग्स रन टाइम पर संयोजन द्वारा गणना नव निर्मित और इसलिए अलग कर रहे हैं।
thusly अपने कोड में परिवर्तित करें:
String str1 = "I'm";
String str2 = " final!";
final String finalString = str1 + str2
और आप (गैर स्थिर संदर्भ में) मिल जाएगा अपने ctor अब है:
मेरी ctor है junk.NewMain $ 1 (जंक। न्यूमेन, जावा.लंग.स्ट्रिंग, जावा.यूटिल। कैलेंडर)
पुhew। मुझे उम्मीद है कि यह समझ में आता है और सहायक था। मैंने बहुत कुछ सीखा, यह निश्चित रूप से है!
क्या होगा यदि कैलेंडर इंस्टेंस अंतिम नहीं था? – SJuan76
@ SJuan76। ... तो आप इसे अज्ञात आंतरिक कक्षा में पारित करने में सक्षम नहीं होते। –