आप जावा में दिए गए वर्ग के सभी उपवर्गों को कैसे खोज सकते हैं?


207

जावा में किसी दिए गए वर्ग (या किसी दिए गए इंटरफ़ेस के सभी कार्यान्वयनकर्ता) के सभी उपवर्गों को खोजने की कोशिश कैसे की जाती है? अब तक, मेरे पास ऐसा करने का एक तरीका है, लेकिन मैं इसे काफी अक्षम (कम से कम कहने के लिए) पाता हूं। विधि है:

  1. उन सभी वर्ग नामों की सूची प्राप्त करें जो वर्ग पथ पर मौजूद हैं
  2. प्रत्येक वर्ग को लोड करें और देखें कि यह वांछित वर्ग या इंटरफ़ेस का उपवर्ग या कार्यान्वयनकर्ता है या नहीं

एक्लिप्स में, टाइप हायरार्की नामक एक अच्छी सुविधा है जो इसे काफी कुशलता से दिखाने का प्रबंधन करती है। किसी के बारे में कैसे जाना जाता है और यह प्रोग्रामेटिक रूप से करता है।


1
यद्यपि प्रतिबिंब और वसंत पर आधारित समाधान दिलचस्प लगते हैं, मुझे कुछ सरल समाधान की आवश्यकता थी जिसमें निर्भरता नहीं थी। ऐसा लगता है कि मेरा मूल कोड (कुछ ट्वीक्स के साथ) जाने का रास्ता था।
एब्रोम

1
निश्चित रूप से आप getSupeClass विधि का पुनरावर्ती उपयोग कर सकते हैं?

मैं विशेष रूप से किसी दिए गए वर्ग के सभी उपवर्गों की तलाश में था । getSuperClass आपको यह नहीं बताएगा कि एक क्लास में क्या उपवर्ग हैं, केवल एक विशिष्ट उपवर्ग के लिए तत्काल सुपर क्लास प्राप्त करें। इसके अलावा, कक्षा में विधि isAignignableFrom आपके सुझाव (पुनरावृत्ति की कोई आवश्यकता नहीं) के लिए बेहतर अनुकूल है।
एवरोम

यह प्रश्न कई अन्य डुप्लिकेट से जुड़ा हुआ है, लेकिन इसमें कोई उपयोगी, सादा जावा उत्तर नहीं है। आह ...
एरिक डुमिनील

जवाबों:


77

आपके द्वारा वर्णित के अलावा इसे करने का कोई अन्य तरीका नहीं है। इसके बारे में सोचें - कोई भी यह कैसे जान सकता है कि क्लासपैथ पर प्रत्येक क्लास को स्कैन किए बिना क्लासएक्स क्या क्लास बढ़ाते हैं?

ग्रहण आपको केवल सुपर और उपवर्गों के बारे में बता सकता है, जो "कुशल" समय की राशि प्रतीत होती है, क्योंकि इसमें पहले से ही उस बिंदु पर लोड किए गए सभी प्रकार के डेटा होते हैं, जहां आप "प्रदर्शन प्रकार पदानुक्रम" बटन दबाते हैं (क्योंकि इसके बाद से) लगातार अपनी कक्षाओं को संकलित करना, कक्षापथ पर सब कुछ के बारे में जानता है, आदि)।


23
अब org.reflections नामक एक साधारण पुस्तकालय है जो इस और अन्य सामान्य प्रतिबिंब कार्यों के साथ मदद करता है। इस लाइब्रेरी के साथ आप सिर्फ reflections.getSubTypesOf(aClazz)) लिंक पर
Enwired

@matt b - अगर इसे सभी वर्गों को स्कैन करना है, तो क्या इसका मतलब यह है कि आपके प्रोजेक्ट में बहुत सी कक्षाएं होने पर भी प्रदर्शन में गिरावट है, भले ही उनमें से कुछ ही आपकी क्लास को सब-क्लास कर रहे हों?
15

बिल्कुल सही। यह सभी वर्गों को छूता है। आप अपने स्वयं के स्कैनर को परिभाषित कर सकते हैं। आप इसे गति दे सकते हैं जैसे कि कुछ विशेष पैकेजों को छोड़कर आप जानते हैं कि आपकी कक्षा को बढ़ाया नहीं जाएगा या सिर्फ कक्षा फ़ाइल को खोलना होगा और कक्षा का नाम खोजने के लिए जाँच करें 'वर्ग में निरंतर खंड प्रतिबिंब स्कैनर को पढ़ने से बचने से बचता है। उन कक्षाओं पर बहुत अधिक जानकारी, जिनमें आपके (प्रत्यक्ष) सुपर क्लास के लिए आवश्यक संदर्भ शामिल नहीं है, अप्रत्यक्ष रूप से आपको आगे स्कैन करने की आवश्यकता है। तो यह सबसे अच्छा है कि इस समय है।
मार्टिन केर्स्टन

Fforw द्वारा जवाब मेरे लिए काम किया और सही जवाब के रूप में चिह्नित किया जाना चाहिए। स्पष्ट रूप से यह क्लासपैथ स्कैनिंग के साथ संभव है।
फारुख नजमी

आप गलत हैं, Burningwave लाइब्रेरी के बारे में नीचे की प्रतिक्रिया देखें

127

शुद्ध जावा के साथ कक्षाओं के लिए स्कैन करना आसान नहीं है।

स्प्रिंग फ्रेमवर्क एक क्लास प्रदान करता है जिसे ClassPathScanningCandidateComponentProvider कहा जाता है जो आपकी आवश्यकता को पूरा कर सकता है। निम्न उदाहरण पैकेज में MyClass के सभी उपवर्गों को मिलेगा। org.example.package

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));

// scan in org.example.package
Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{
    Class cls = Class.forName(component.getBeanClassName());
    // use class cls found
}

इस पद्धति का एक अतिरिक्त लाभ यह है कि यह जो स्कैन करता है सभी वर्गों को लोड नहीं करेगा उम्मीदवारों को खोजने के लिए एक बायोटेक विश्लेषक का उपयोग करने का अतिरिक्त लाभ है ।


23
डिफ़ॉल्ट फ़िल्टर को अक्षम करने के लिए ClassPathScanningCandidateComponentProvider बनाते समय गलत तरीके को पैरामीटर के रूप में पास किया जाना चाहिए। डिफ़ॉल्ट फ़िल्टर अन्य प्रकार की कक्षाओं से मेल खाएँगे, उदाहरण के लिए @Component के साथ कुछ भी एनोटेट। हम केवल यह चाहते हैं कि यहां AssignableTypeFilter सक्रिय हो।
एमसीडीएस

आप कहते हैं कि यह आसान नहीं है, लेकिन हम इसे शुद्ध जावा के साथ करना चाहते हैं तो हम इसे कैसे करेंगे?
असपितास

49

यह केवल अंतर्निहित जावा रिफ्लेक्शंस एपीआई का उपयोग करना संभव नहीं है।

एक परियोजना मौजूद है जो आपके वर्गपथ की आवश्यक स्कैनिंग और अनुक्रमण करती है ताकि आप इस जानकारी तक पहुँच प्राप्त कर सकें ...

कुछ विचार

Scannotations की भावना में जावा रनटाइम मेटाडेटा विश्लेषण

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

उन प्रतिबिंबों का उपयोग करना जिनके लिए आप अपनी मेटाडेटा को क्वेरी कर सकते हैं:

  • सभी प्रकार के सभी उपप्रकार प्राप्त करें
  • कुछ एनोटेशन के साथ सभी प्रकार के एनोटेट प्राप्त करें
  • कुछ प्रकार के एनोटेशन के साथ एनोटेशन प्राप्त करें, जिसमें एनोटेशन मापदंडों का मिलान शामिल है
  • कुछ के साथ एनोटेट सभी तरीके प्राप्त करें

(अस्वीकरण: मैंने इसका उपयोग नहीं किया है, लेकिन परियोजना का विवरण आपकी आवश्यकताओं के लिए सटीक है।)


1
दिलचस्प। इस परियोजना में कुछ निर्भरताएँ हैं, जिनका उनके दस्तावेज़ीकरण में उल्लेख नहीं है। अर्थात् (जिन्हें मैंने अब तक पाया है): javaassist, log4J, XStream
Avrom

3
मैंने मावेन के साथ इस प्रॉजेक्ट को शामिल किया और इसने ठीक काम किया। उपवर्ग प्राप्त करना वास्तव में पहला स्रोत कोड उदाहरण है और इसकी दो पंक्तियाँ लंबी हैं :-)
कर्ल्सफ्रीड

क्या केवल अंतर्निहित जावा रिफ्लेक्शंस एपीआई या ऐसा करने के लिए बहुत असुविधाजनक उपयोग करना संभव नहीं है?
फ्लो

1
कृपया सावधान रहें जब आप प्रतिबिंब का उपयोग करने जा रहे हैं और तब ग्लासफ़िश के लिए अपना ऐप WAR तैनात करें! अमरूद लाइब्रेरी में संघर्ष है और तैनाती सीडीआई की विफलता के साथ विफल हो जाएगी : WELD-001408 - अधिक जानकारी के लिए कृपया GLASSFISH-20579 देखें। FastClasspathScanner इस मामले में एक समाधान है।
लू_को

मैं सिर्फ इस परियोजना की कोशिश करता हूं और यह काम करता है। मैं सिर्फ रणनीति डिजाइन पैटर्न को बढ़ाने के लिए इसका उपयोग करता हूं और सभी रणनीति कंक्रीट वर्ग (उपवर्ग) प्राप्त करता हूं मैं बाद वाले डेमो को साझा करूंगा।
शिन मेंग

10

यह मत भूलो कि एक वर्ग के लिए उत्पन्न Javadoc में ज्ञात उपवर्गों की एक सूची शामिल होगी (और इंटरफेस के लिए, ज्ञात कार्यान्वयन कक्षाएं)।


3
यह पूरी तरह से गलत है, सुपर क्लास को अपने उप वर्गों पर निर्भर नहीं होना चाहिए, यहां तक ​​कि javadoc या टिप्पणी में भी नहीं।
शिकारी

@ शिकारी मुझसे असहमत हैं। यह पूरी तरह से सही है कि JavaDoc में ज्ञात उपवर्गों की एक सूची शामिल है । बेशक, "ज्ञात" में वह वर्ग शामिल नहीं हो सकता है जिसे आप ढूंढ रहे हैं, लेकिन कुछ उपयोग मामलों के लिए यह पर्याप्त होगा।
Qw3ry

और आपको किसी भी मामले में कुछ कक्षाएं याद आ सकती हैं: मैं क्लासपैथ (रनटाइम के दौरान) में एक नया जार लोड कर सकता हूं और इससे पहले हुई हर पहचान विफल हो जाएगी।
Qw3ry

10

ClassGraph आज़माएँ । (डिस्क्लेमर, मैं लेखक हूं)। क्लासग्राफ किसी दिए गए वर्ग के उपवर्गों के लिए स्कैनिंग का समर्थन करता है, या तो रनटाइम या बिल्ड टाइम पर, लेकिन साथ ही बहुत अधिक। क्लासग्राफ पूरे क्लास ग्राफ (सभी वर्गों, एनोटेशन, विधियों, विधि मापदंडों, और फ़ील्ड्स) का एक सार प्रतिनिधित्व मेमोरी में बना सकता है, क्लासपैथ पर सभी कक्षाओं के लिए, या श्वेतसूची वाले संकुल में कक्षाओं के लिए, और आप क्लास ग्राफ को क्वेरी कर सकते हैं तुम्हें चाहिए। ClassGraph का समर्थन करता है और अधिक classpath विनिर्देश तंत्र और classloaders किसी अन्य स्कैनर से, और भी नई JPMS मॉड्यूल प्रणाली के साथ सहजता से चलता है, इसलिए यदि आप ClassGraph पर अपने कोड के आधार पर, अपने कोड अधिकतम पोर्टेबल हो जाएगा। यहाँ एपीआई देखें।


9

मैंने कई साल पहले ऐसा किया था। ऐसा करने का सबसे विश्वसनीय तरीका (यानी आधिकारिक जावा एपीआई और कोई बाहरी निर्भरता नहीं है) एक सूची बनाने के लिए एक कस्टम डॉकलेट लिखना है जिसे रनटाइम पर पढ़ा जा सकता है।

आप इसे कमांड लाइन से इस तरह चला सकते हैं:

javadoc -d build -doclet com.example.ObjectListDoclet -sourcepath java/src -subpackages com.example

या इसे इस तरह से चींटी से चलाएं:

<javadoc sourcepath="${src}" packagenames="*" >
  <doclet name="com.example.ObjectListDoclet" path="${build}"/>
</javadoc>

यहाँ मूल कोड है:

public final class ObjectListDoclet {
    public static final String TOP_CLASS_NAME =  "com.example.MyClass";        

    /** Doclet entry point. */
    public static boolean start(RootDoc root) throws Exception {
        try {
            ClassDoc topClassDoc = root.classNamed(TOP_CLASS_NAME);
            for (ClassDoc classDoc : root.classes()) {
                if (classDoc.subclassOf(topClassDoc)) {
                    System.out.println(classDoc);
                }
            }
            return true;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }
}

सादगी के लिए, मैंने कमांड लाइन तर्क पार्सिंग को हटा दिया है और मैं फाइल के बजाय System.out को लिख रहा हूं।


इस प्रोग्राम का उपयोग करते समय मुश्किल हो सकता है, मुझे कहना होगा - एक स्मार्ट दृष्टिकोण!
जनक बंडारा

8

मुझे पता है कि मुझे इस पार्टी में कुछ साल देर हो चुकी है, लेकिन मैं इस सवाल को हल करने की कोशिश में आया था। आप ग्रहण के आंतरिक खोज का उपयोग प्रोग्रामिक रूप से कर सकते हैं, यदि आप एक ग्रहण प्लगिन लिख रहे हैं (और इस प्रकार उनकी कैशिंग का लाभ उठा सकते हैं, आदि), उन वर्गों को खोजने के लिए जो एक इंटरफ़ेस लागू करते हैं। यहाँ मेरा (बहुत मोटा) पहला कट है:

  protected void listImplementingClasses( String iface ) throws CoreException
  {
    final IJavaProject project = <get your project here>;
    try
    {
      final IType ifaceType = project.findType( iface );
      final SearchPattern ifacePattern = SearchPattern.createPattern( ifaceType, IJavaSearchConstants.IMPLEMENTORS );
      final IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
      final SearchEngine searchEngine = new SearchEngine();
      final LinkedList<SearchMatch> results = new LinkedList<SearchMatch>();
      searchEngine.search( ifacePattern, 
      new SearchParticipant[]{ SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {

        @Override
        public void acceptSearchMatch( SearchMatch match ) throws CoreException
        {
          results.add( match );
        }

      }, new IProgressMonitor() {

        @Override
        public void beginTask( String name, int totalWork )
        {
        }

        @Override
        public void done()
        {
          System.out.println( results );
        }

        @Override
        public void internalWorked( double work )
        {
        }

        @Override
        public boolean isCanceled()
        {
          return false;
        }

        @Override
        public void setCanceled( boolean value )
        {
        }

        @Override
        public void setTaskName( String name )
        {
        }

        @Override
        public void subTask( String name )
        {
        }

        @Override
        public void worked( int work )
        {
        }

      });

    } catch( JavaModelException e )
    {
      e.printStackTrace();
    }
  }

मुझे अब तक जो पहली समस्या दिख रही है, वह यह है कि मैं केवल उन कक्षाओं को पकड़ रहा हूं जो सीधे इंटरफ़ेस को लागू करते हैं, उनके सभी उपवर्गों को नहीं - लेकिन थोड़ी सी पुनरावृत्ति कभी भी किसी को चोट नहीं पहुंचाती है।


3
या, यह पता चला है कि आपको अपनी खोज करने की आवश्यकता नहीं है। आप बस अपने IType से सीधे एक ITypeHierarchy प्राप्त कर सकते हैं। उस पर .newTypeHierarchy (): dev.eclipse.org/newslists/news.eclipse.tools.jdt -msg05036.html
Curtis

7

अन्य उत्तरों में उल्लिखित सीमाओं को ध्यान में रखते हुए, आप निम्नलिखित तरीके से ओपनपोजोPojoClassFactory ( मावेन पर उपलब्ध ) का उपयोग कर सकते हैं :

for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(packageRoot, Superclass.class, null)) {
    System.out.println(pojoClass.getClazz());
}

जहाँ packageRootआप (जैसे "com.mycompany"या यहाँ तक कि "com") में खोज करना चाहते हैं, उन पैकेजों का रूट स्ट्रिंग है , और Superclassआपका सुपरपाइप है (यह इंटरफेस पर भी काम करता है)।


अब तक सुझाए गए लोगों से सबसे तेज और सबसे सुंदर समाधान।
किडक्रिप्लर

4

मैं org.reflections.Reflectionsसार वर्ग के उपवर्ग प्राप्त करने के लिए उपयोग करने के लिए एक सरल डेमो लिखता हूं :

https://github.com/xmeng1/ReflectionsDemo


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

4

आपकी विशेष आवश्यकताओं के आधार पर, कुछ मामलों में जावा के सेवा लोडर तंत्र को प्राप्त हो सकता है।

संक्षेप में, यह डेवलपर्स को स्पष्ट रूप से यह घोषणा करने की अनुमति देता है कि एक वर्ग JAR / WAR फ़ाइल की META-INF/servicesनिर्देशिका में किसी फ़ाइल में सूचीबद्ध करके किसी अन्य वर्ग (या कुछ इंटरफ़ेस को लागू करता है) को उपवर्गित करता है । यह तब java.util.ServiceLoaderवर्ग का उपयोग करके खोजा जा सकता है , जब कोई Classवस्तु दी जाती है, तो उस वर्ग के सभी घोषित उपवर्गों के उदाहरण उत्पन्न होंगे (या, यदि Classएक इंटरफ़ेस का प्रतिनिधित्व करता है , तो उस इंटरफ़ेस को लागू करने वाले सभी वर्ग)।

इस दृष्टिकोण का मुख्य लाभ यह है कि उपवर्गों के लिए पूरे क्लासपाथ को मैन्युअल रूप से स्कैन करने की आवश्यकता नहीं है - सभी खोज तर्क ServiceLoaderकक्षा के भीतर समाहित हैं , और यह केवल META-INF/servicesनिर्देशिका में घोषित वर्गों को लोड करता है (क्लासपाथ पर हर वर्ग नहीं) ।

हालाँकि, कुछ नुकसान हैं:

  • यह सभी उपवर्गों को नहीं मिलेगा , केवल वे ही स्पष्ट रूप से घोषित किए जाएंगे । जैसे, यदि आपको वास्तव में सभी उपवर्गों को खोजने की आवश्यकता है, तो यह दृष्टिकोण अपर्याप्त हो सकता है।
  • इसके लिए डेवलपर को META-INF/servicesनिर्देशिका के तहत कक्षा को स्पष्ट रूप से घोषित करने की आवश्यकता होती है । यह डेवलपर पर एक अतिरिक्त बोझ है, और त्रुटि-प्रवण हो सकता है।
  • ServiceLoader.iterator()उपवर्ग उदाहरणों, न कि उनका उत्पन्न Classवस्तुओं। यह दो मुद्दों का कारण बनता है:
    • सबक्लासेस का निर्माण कैसे किया जाता है, इस बारे में आपको कोई जानकारी नहीं है - इंस्टेंसेस बनाने के लिए नो-आर्ग कंस्ट्रक्टर का उपयोग किया जाता है।
    • जैसे, उपवर्गों में एक डिफ़ॉल्ट निर्माता होना चाहिए, या अन्वेषण को एक नो-आर्ग कंस्ट्रक्टर घोषित करना चाहिए।

जाहिरा तौर पर जावा 9 इनमें से कुछ कमियों को संबोधित करेगा (विशेष रूप से, उपवर्गों की तात्कालिकता के बारे में)।

एक उदाहरण

मान लीजिए कि आप एक इंटरफ़ेस लागू करने वाली कक्षाएं ढूंढने में रुचि रखते हैं com.example.Example:

package com.example;

public interface Example {
    public String getStr();
}

वर्ग com.example.ExampleImplइंटरफ़ेस लागू करता है:

package com.example;

public class ExampleImpl implements Example {
    public String getStr() {
        return "ExampleImpl's string.";
    }
}

आप घोषणा करेंगे कि कक्षा में पाठ युक्त एक फ़ाइल बनाकर एक ExampleImplकार्यान्वयन है ।ExampleMETA-INF/services/com.example.Examplecom.example.ExampleImpl

फिर, आप निम्न के प्रत्येक कार्यान्वयन का Exampleएक उदाहरण (उदाहरण सहित ExampleImpl) प्राप्त कर सकते हैं:

ServiceLoader<Example> loader = ServiceLoader.load(Example.class)
for (Example example : loader) {
    System.out.println(example.getStr());
}

// Prints "ExampleImpl's string.", plus whatever is returned
// by other declared implementations of com.example.Example.

3

यह भी ध्यान दिया जाना चाहिए कि यह निश्चित रूप से केवल उन सभी उपवर्गों को खोजेगा जो आपके वर्तमान वर्गपथ पर मौजूद हैं। संभवतः यह ठीक है कि आप वर्तमान में क्या देख रहे हैं, और संभावना है कि आपने इस पर विचार किया था, लेकिन अगर आपने किसी भी गैर- finalवर्ग को जंगली ("जंगली" के अलग-अलग स्तरों के लिए) जारी किया है, तो यह पूरी तरह से संभव है किसी और ने अपना उपवर्ग लिखा है जिसके बारे में आप नहीं जानते होंगे।

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


3

आपके कार्यान्वयन और ग्रहण के बीच अंतर देखने का कारण यह है कि आप हर बार स्कैन करते हैं, जबकि एक्लिप्स (और अन्य उपकरण) केवल एक बार स्कैन करते हैं (परियोजना लोड के दौरान अधिकतर) और एक सूचकांक बनाते हैं। अगली बार जब आप डेटा मांगते हैं तो वह फिर से स्कैन नहीं करता है, लेकिन सूचकांक को देखें।


3

मैं एक प्रतिबिंब lib का उपयोग कर रहा हूं, जो आपके वर्गपथ को सभी उपवर्गों के लिए स्कैन करता है: https://github.com/ronmamo/reflections

यह इस प्रकार किया जाएगा:

Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);

2

उन्हें स्थैतिक मानचित्र में जोड़ें (this.getClass ()। GetName ()) पैरेंट क्लासेस कंस्ट्रक्टर (या एक डिफ़ॉल्ट बनाएं) लेकिन यह रनटाइम में अपडेट हो जाएगा। यदि आलसी आरंभीकरण एक विकल्प है तो आप इस दृष्टिकोण की कोशिश कर सकते हैं।


1

आप org.reflections लाइब्रेरी का उपयोग कर सकते हैं और फिर, रिफ्लेक्शंस क्लास का ऑब्जेक्ट बना सकते हैं। इस ऑब्जेक्ट का उपयोग करके, आप दिए गए वर्ग के सभी उपवर्गों की सूची प्राप्त कर सकते हैं। https://www.javadoc.io/doc/org.reflections/reflections/0.9.10/org/reflections/Reflections.html

    Reflections reflections = new Reflections("my.project.prefix");
    System.out.println(reflections.getSubTypesOf(A.class)));

0

मुझे एक परीक्षण के मामले के रूप में ऐसा करने की आवश्यकता थी, यह देखने के लिए कि क्या नई कक्षाओं को कोड में जोड़ा गया था। यह जो मैंने किया है

final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
private static ArrayList<String> files = new ArrayList<String>();
listFilesForFolder(rootFolder); 

@Test(timeout = 1000)
public void testNumberOfSubclasses(){
    ArrayList<String> listSubclasses = new ArrayList<>(files);
    listSubclasses.removeIf(s -> !s.contains("Superclass.class"));
    for(String subclass : listSubclasses){
        System.out.println(subclass);
    }
    assertTrue("You did not create a new subclass!", listSubclasses.size() >1);     
}

public static void listFilesForFolder(final File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            listFilesForFolder(fileEntry);
        } else {
            files.add(fileEntry.getName().toString());
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.