2008-12-12 26 views
186

आइए कहें कि मेरे पास एक ठोस वर्ग कक्षा 1 है और मैं इसमें से एक अज्ञात वर्ग बना रहा हूं।किसी अज्ञात वर्ग के निर्माता का उपयोग

Object a = new Class1(){ 
     void someNewMethod(){ 
     } 
     }; 

अब इस अज्ञात वर्ग के निर्माता को अधिभारित करने का कोई तरीका है। नीचे दिखाए गए

Object a = new Class1(){ 
     void someNewMethod(){ 
     } 
     public XXXXXXXX(int a){ 
      super(); 
      System.out.println(a); 
     } 
     }; 

xxxxxxxx पर कुछ के साथ निर्माता का नाम देने के लिए?

+4

पढ़ने के लायक है [डबलब्रेस प्रारंभिकरण] (http://c2.com/cgi/wiki?DoubleBraceInitialization) –

उत्तर

240

Java Language Specification से, खंड 15.9.5.1:

एक अनाम वर्ग एक स्पष्ट रूप से घोषित निर्माता नहीं हो सकता।

क्षमा करें :(

संपादित करें: एक विकल्प के रूप में, आप कुछ अंतिम स्थानीय चर बना सकते हैं, और/या गुमनाम कक्षा में एक उदाहरण प्रारंभकर्ता शामिल उदाहरण के लिए:।

public class Test { 
    public static void main(String[] args) throws Exception { 
     final int fakeConstructorArg = 10; 

     Object a = new Object() { 
      { 
       System.out.println("arg = " + fakeConstructorArg); 
      } 
     }; 
    } 
} 

यह गड़बड़, लेकिन यह सिर्फ आपकी मदद कर सकता है। वैकल्पिक रूप से, उचित नेस्टेड क्लास का उपयोग करें :)

+1

मैंने इसे जोड़ने से पहले वास्तव में आपका समाधान नहीं देखा था। –

+16

अर्ने, मुझे विश्वास है कि उसने इसे कॉपी नहीं किया है। वह पर्याप्त जावा को इतना श्रेय देने के लिए पर्याप्त जानता है कि जब वह इसे कॉपी करता तो मुझे लगता है। –

+18

ओएमजी, क्या किसी ने कॉपी करने के लिए जॉन स्कीट को दोषी ठहराया? – user

85

यह संभव नहीं है, लेकिन आप इस तरह एक अज्ञात प्रारंभकर्ता जोड़ सकते हैं:

final int anInt = ...; 
Object a = new Class1() 
{ 
    { 
    System.out.println(anInt); 
    } 

    void someNewMethod() { 
    } 
}; 

अज्ञात वर्ग द्वारा उपयोग किए जाने वाले स्थानीय चर या पैरामीटर की घोषणाओं पर अंतिम मत भूलना, जैसा कि मैंने इसे एक इंट के लिए किया था।

1

किसी अज्ञात वर्ग में नामित ओवरलोडेड कन्स्ट्रक्टर रखने का कोई अर्थ नहीं है, क्योंकि इसे कॉल करने का कोई तरीका नहीं होगा, वैसे भी।

आप जो वास्तव में करने की कोशिश कर रहे हैं उसके आधार पर, कक्षा के बाहर घोषित अंतिम स्थानीय चर का उपयोग करना, या आर्ने द्वारा दिखाए गए उदाहरण प्रारंभकर्ता का उपयोग करना सबसे अच्छा समाधान हो सकता है।

+0

भाषा आसानी से "सामान्य" "वांछित अगर अज्ञात वर्ग के लिए तर्क में कन्स्ट्रक्टर तर्क। कन्स्ट्रक्टर घोषणा के लिए वाक्यविन्यास शायद बहुत अजीब लग रहा है हालांकि ... –

+0

क्या यह केवल कन्स्ट्रक्टर घोषित नहीं कर सकता है जैसे कि यह बेस क्लास कन्स्ट्रक्टर था? मुझे उस –

2

हां, यह सही है कि आप बेनामी वर्ग में निर्माण को परिभाषित नहीं कर सकते हैं, लेकिन इसका मतलब यह नहीं है कि अज्ञात वर्ग में कन्स्ट्रक्टर नहीं है। उलझन में ... दरअसल आप एक बेनामी वर्ग में निर्माण को परिभाषित नहीं कर सकते हैं लेकिन संकलक इसके मूल निर्माता के रूप में उसी हस्ताक्षर के साथ एक कन्स्ट्रक्टर उत्पन्न करता है। माता-पिता एक से अधिक निर्माता है, गुमनाम

65

यहाँ समस्या को हल एक और तरीका है एक और केवल एक निर्माता होगा:

public class Test{ 

    public static final void main(String...args){ 

     Thread t = new Thread(){ 

      private String message = null; 

      Thread initialise(String message){ 

       this.message = message; 
       return this; 
      } 

      public void run(){ 
       System.out.println(message); 
      } 
     }.initialise(args[0]).start(); 
    } 
} 
+17

के साथ समस्याएं नहीं दिख रही हैं, लेकिन थ्रेड का उपयोग इसे पहले कुछ हद तक भ्रामक बनाता है (एक पल के लिए मैंने सोचा था कि आपको सामान शुरू करने के लिए एक अलग थ्रेड बनाया गया था!) ​​ – scorpiodawg

+6

ध्यान दें कि 'टी' परिभाषित करने के बाद आप टी नहीं कह सकते हैं।प्रारंभ() 'जब तक कि यह कार्य कक्षा/इंटरफ़ेस प्रकार में परिभाषित नहीं किया जाता है। –

+1

@AramKocharyan यह इसे एक कन्स्ट्रक्टर की तरह और भी काम करता है। – v010dya

1

मेरे मामले में, एक स्थानीय वर्ग (कस्टम निर्माता के साथ) के रूप में काम एक अनाम वर्ग:

Object a = getClass1(x); 

public Class1 getClass1(int x) { 
    class Class2 implements Class1 { 
    void someNewMethod(){ 
    } 
    public Class2(int a){ 
     super(); 
     System.out.println(a); 
    } 
    } 
    Class1 c = new Class2(x); 
    return c; 
} 
2

आप न तर्क पारित करने के लिए की जरूरत है, तो प्रारंभकर्ता कोड के लिए पर्याप्त है, लेकिन यदि आप एक contrcutor से तर्क पारित करने के लिए की जरूरत है अधिकांश मामलों को हल करने के लिए एक रास्ता है, तो:

+०१२३५१६४१०
Boolean var= new anonymousClass(){ 
    private String myVar; //String for example 

    @Overriden public Boolean method(int i){ 
      //use myVar and i 
    } 
    public String setVar(String var){myVar=var; return this;} //Returns self instane 
}.setVar("Hello").method(3); 
+0

यदि मैं आपका कोड अज्ञात क्लास को स्ट्रिंग से प्राप्त करना चाहता हूं (setVar स्ट्रिंग का प्रकार है और इसे वापस करता है), लेकिन स्ट्रिंग विस्तार योग्य नहीं है। मुझे लगता है कि setVar को वापस करना चाहिए जो अनाम क्लास से निकलता है। – alfoks

3

आपके पास सार तत्वों में एक कन्स्ट्रक्टर हो सकता है जो इनिट पैरामीटर स्वीकार करता है। जावा स्पेक केवल निर्दिष्ट करता है कि अज्ञात वर्ग, जो (वैकल्पिक रूप से) सार वर्ग या इंटरफ़ेस के कार्यान्वयन की संतान है, उसके पास अपने स्वयं के अधिकार से कोई कन्स्ट्रक्टर नहीं हो सकता है।

static abstract class Q{ 
    int z; 
    Q(int z){ this.z=z;} 
    void h(){ 
     Q me = new Q(1) { 
     }; 
    } 
} 

आप संभावना सार वर्ग अपने आप को लिखने के लिए है, तो इस तरह के एक निर्माता वहाँ रख दिया और धाराप्रवाह एपीआई का उपयोग जहां कोई बेहतर समाधान है:

निम्नलिखित बिल्कुल कानूनी और संभव है। आप इस तरह से अपने मूल वर्ग के निर्माता को पैरामीटर के साथ एक कन्स्ट्रक्टर के साथ नामित भाई वर्ग बना सकते हैं और इसका उपयोग अपनी अनाम कक्षा को तुरंत चालू करने के लिए कर सकते हैं।

1

पीटर Norvig की द जावा IAQ: कभी कभी उत्तर दिए गए प्रश्न

http://norvig.com/java-iaq.html#constructors - बेनामी वर्ग contructors

http://norvig.com/java-iaq.html#init - Construtors और आरंभीकरण

संक्षेप, तो आप कुछ इस तरह का निर्माण कर सकते ..

public class ResultsBuilder { 
    Set<Result> errors; 
    Set<Result> warnings; 

... 

    public Results<E> build() { 
     return new Results<E>() { 
      private Result[] errorsView; 
      private Result[] warningsView; 
      { 
       errorsView = ResultsBuilder.this.getErrors(); 
       warningsView = ResultsBuilder.this.getWarnings(); 
      } 

      public Result[] getErrors() { 
       return errorsView; 
      } 

      public Result[] getWarnings() { 
       return warningsView; 
      } 
     }; 
    } 

    public Result[] getErrors() { 
     return !isEmpty(this.errors) ? errors.toArray(new Result[0]) : null; 
    } 

    public Result[] getWarnings() { 
     return !isEmpty(this.warnings) ? warnings.toArray(new Result[0]) : null; 
    } 
} 
+0

मुझे Google के वैज्ञानिक पीटर नॉरविग को नहीं पता था, शायद यह उनके शुरुआती काम में से एक है, यह जावा 1.1 के बारे में है! एक ऐतिहासिक दृष्टिकोण पर दिलचस्प :) – pdem

12

मुझे पता है कि उत्तर पोस्ट करने के लिए धागा बहुत पुराना है। लेकिन फिर भी मुझे लगता है कि यह इसके लायक है।

हालांकि आपके पास एक स्पष्ट कन्स्ट्रक्टर नहीं हो सकता है, यदि आपका इरादा सुपर क्लास के कन्स्ट्रक्टर को कॉल करना है, तो निम्नलिखित आपको बस इतना करना है।

StoredProcedure sp = new StoredProcedure(datasource, spName) { 
    {// init code if there are any} 
}; 

यह एक DataSource और एक String वस्तु पारित करके वसंत में एक StoredProcedure वस्तु बनाने का एक उदाहरण है।

तो नीचे की रेखा है, यदि आप एक अज्ञात वर्ग बनाना चाहते हैं और सुपर क्लास कन्स्ट्रक्टर को कॉल करना चाहते हैं तो सुपर क्लास कन्स्ट्रक्टर से मेल खाने वाले हस्ताक्षर के साथ अज्ञात वर्ग बनाएं।

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