2012-11-29 8 views
6

यदि आपके पास एक अमूर्त वर्ग है तो आप इसे एक ठोस अज्ञात वर्ग प्राप्त करके तुरंत चालू कर सकते हैं। यह एक उदाहरण है:जावा में क्लास ऑब्जेक्ट में संग्रहीत एक अमूर्त वर्ग को अनामित रूप से कैसे प्रारंभ करें?

abstract class A { 
    abstract void hello(); 
} 

A say = new A() { void hello() { System.out.println ("hello"); } } 

say.hello(); // -> hello 

क्लास ऑब्जेक्ट में कक्षा संग्रहीत होने पर ऐसा कैसे करें?

// -*- compile-command: "javac anon.java && java anon"; -*- 

class anon 
{ 
    anon() throws Exception {} 

    abstract class AbstractClass 
    { 
     AbstractClass() throws Exception {} 
     abstract void id(); 
    } 

    AbstractClass x = new AbstractClass() 
     { 
      void id() { System.out.println ("X"); } 
     }; 

    Class<AbstractClass> abstractclass 
     = (Class<AbstractClass>)Class.forName ("anon$AbstractClass"); 

    AbstractClass y = abstractclass.getConstructor().newInstance(); 

    public static void main (String argv[]) throws Exception 
    { 
     anon main = new anon(); 
     main.x.id(); // should print "X" 
     main.y.id(); // should print "Y" 
    } 
} 

पहले इन्स्टेन्शियशन (एक्स) काम करता है ठीक लेकिन दूसरे (y) में विफल रहता है, क्योंकि यह एक ठोस वर्ग पाने के बिना सीधे सार वर्ग का दृष्टांत की कोशिश करता है: यहाँ एक उदाहरण है। मैं जावा में केवल क्लास ऑब्जेक्ट के साथ ऐसा कैसे कर सकता हूं?

+0

रुको। क्या आपने पहले कोड के साथ दूसरे तरीके को लागू करने का प्रयास किया था? मुझे लगता है कि यह वहां भी काम नहीं करेगा। आप इस तरह एक अमूर्त वर्ग को तुरंत चालू करने की कोशिश क्यों कर रहे हैं? जब आप एक अज्ञात वर्ग बनाते हैं, तो आप वास्तव में अपनी अमूर्त कक्षा का विस्तार कर रहे हैं और इसे तत्काल बना रहे हैं, न कि अमूर्त वर्ग स्वयं। –

+0

कोई y.id() "वाई" मुद्रित करना चाहिए। – ceving

+0

@ceving .. क्या आप मेरी टिप्पणी समझ गए थे? –

उत्तर

5

आपको अज्ञात कक्षाएं वास्तव में काम करने के तरीके पर गलतफहमी हो सकती है। एक अज्ञात वर्ग वास्तव में किसी अन्य की तरह नियमित कक्षा है और इसकी अपनी कक्षा फ़ाइल है। जावा-द-भाषा केवल इस पर कुछ वाक्य रचनात्मक चीनी प्रदान करती है और किसी ऐसी चीज़ के लिए कम वर्बोज़ सिंटैक्स की अनुमति देती है जिसे आप नियमित रूप से नामित शीर्ष-स्तरीय कक्षा को अपनी फ़ाइल में घोषित करके नकल कर सकते हैं। यही कारण है कि आप प्रतिबिंब API को बेकार पाएंगे जो आप प्राप्त करना चाहते हैं। असल में, आप गतिशील रूप से उस वर्ग को बनाना चाहते हैं जिसमें इसकी कक्षा फ़ाइल न हो। इसके लिए आपको उपयुक्त पुस्तकालय की आवश्यकता है, जैसे कि javassist

+0

बहुत बुरा। जब भी मुझे जावा लिखना पड़ेगा तो मुझे जावा की सीमाओं को रोकने के लिए काफी समय बिताना होगा। लेकिन इस बार दीवार एक चट्टान चेहरे की तरह दिखती है। – ceving

+1

काफी सच है। जावा को एक चट्टान से तुलना करना वास्तव में एक बहुत ही उपजाऊ समानता है और कई अलग-अलग मामलों के लिए काम करता है। मुझे जावा की लेगो ईंटों के विरोध में रूबी और जावास्क्रिप्ट जैसी गतिशील भाषाओं के लिए मिट्टी की कल्पना करना पसंद है। वे केवल कुछ संकीर्ण और पूर्वनिर्धारित तरीकों से जुड़ते हैं। –

+0

हमम मुझे खुद को कुछ लेगो ईंटों को कुछ बनाने के लिए याद कर सकते हैं। अनुवांशिक रूप से निर्धारित किया जाना चाहिए कि मुझे यह समस्याएं हैं। – ceving

1

यदि A एक अमूर्त वर्ग के बजाय एक इंटरफेस होगा, तो आप इसे गतिशील प्रॉक्सी के साथ कर सकते हैं, लेकिन यह एक अमूर्त वर्ग के साथ काम नहीं करता है। यह इंटरफ़ेस के साथ कैसे काम करता है इसका उदाहरण:

import java.lang.reflect.InvocationHandler; 
import java.lang.reflect.Method; 
import java.lang.reflect.Proxy; 

interface A { 
    void hello(); 
} 

public class Example { 
    public static void main(String[] args) throws Exception { 
     @SuppressWarnings("unchecked") 
     Class<A> cls = (Class<A>) Class.forName("A"); 

     InvocationHandler handler = new InvocationHandler() { 
      @Override 
      public Object invoke(Object proxy, Method method, Object[] args) 
        throws Throwable { 
       System.out.println(method.getName()); 
       return null; 
      } 
     }; 

     A instance = (A) Proxy.newProxyInstance(cls.getClassLoader(), 
      new Class<?>[] { cls }, handler); 

     instance.hello(); 
    } 
} 
+0

हम्म एक अजीब नई जावा सीमा की तरह लगता है मुझे अभी तक पता नहीं है: कुछ ऐसा जो इंटरफेस के साथ किया जा सकता है लेकिन सार वर्गों के साथ नहीं, हालांकि वे लगभग समान हैं। – ceving

0

सार कक्षाओं को तत्काल नहीं किया जा सकता है, इसलिए आपको वास्तव में एक नई ठोस कक्षा की आवश्यकता है जो अमूर्त वर्ग को बढ़ाती है। कक्षा कोड से जावा कंपाइलर द्वारा कक्षाएं बनाई जाती हैं। तो उस स्रोत कोड को लिखें और जावा कंपाइलर चलाएं। यह गतिशील रूप से करना आसान नहीं है, क्योंकि जावा कंपाइलर को फ़ाइल में रहने के लिए स्रोत कोड की आवश्यकता होती है और संकलित कक्षाओं को फ़ाइल सिस्टम में भी रखता है, लेकिन संभव है। देखें कि इसे Generating Java classes dynamically पर कैसे करना है। फिर आपको संकलित कक्षाएं लोड करनी होंगी, जो एक और कहानी है।

यदि आप इसे "जावा सीमा" के रूप में देखते हैं, तो शायद आपने अपने कार्य के लिए गलत भाषा (या गलत कार्य बंद कर दिया) का चयन किया है। JVM के आधार पर गतिशील भाषाओं का प्रयास करें: ग्रोवी, जेआरबी ... उनमें से बहुत सारे हैं।

+0

क्या आप एक भाषा चुनने के लिए स्वतंत्र हैं? तुम भाग्यशाली चीज! – ceving

+0

आप हर जगह जावा का उपयोग कर सकते हैं, लेकिन इस कार्य के लिए जावा से ग्रोवी को कॉल करें। –

0

मार्को ने कहा, एक अनाम वर्ग फ़ाइल और बाइट कोड स्तर पर किसी अन्य के जैसा ही है। यह सिर्फ भाषा स्तर वाक्य रचनात्मक चीनी है जो छोटे वर्गों को लिखना आसान बनाता है।

आपके उदाहरण में, x.getClass()abstract कक्षा नहीं है। यह AbstractClass का उप-वर्ग है, जो id() की परिभाषा से अब abstract नहीं है। इसका शायद नाम anon$1 है।

बेशक, अगर यह अमूर्त था, तो आप इसे तुरंत चालू नहीं कर सके। यह वही है जो आप y के असाइनमेंट में करने की कोशिश कर रहे हैं। आपका प्रतिबिंब y = anon.AbstractClass(); के बराबर है id() ओवरराइडिंग के साथ। प्रतिबिंब रनटाइम पर त्रुटि कर रहा है जैसे कि कथन संकलन समय में त्रुटि होगी। उस बिंदु करने के लिए

Class<AbstractClass> abstractclass 
    = (Class<AbstractClass>)Class.forName("anon$1"); // Note the different class name 
AbstractClass y = abstractclass.getConstructor().newInstance(); 
y.id(); // prints "X", not "Y" 

...:

निम्नलिखित संभावना (अन्य अज्ञात वर्गों के अस्तित्व निर्भर करता है, और उनके क्रम) होता है और बिना किसी त्रुटि के चलते हैं, लेकिन प्रिंट "एक्स"

main.y.id(); // should print "Y" 

कहीं अपने कोड में आप एक लाइन है कि एक "Y" चरित्र प्रिंट की क्या ज़रूरत है, इसलिए वहाँ यह उम्मीद करना किसी भी कारण नहीं होना चाहिए।

+0

यह बिल्कुल सवाल था कि लाइन प्रिंटिंग "वाई" कैसे लिखना है। – ceving

+0

आपके कोड में कहीं भी नहीं है System.out.println ("वाई"); 'मौजूद है। आपकी टिप्पणी (कोड में) अमान्य है। – Anm

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