আপনি জাভাতে প্রদত্ত শ্রেণীর সমস্ত উপক্লাগুলি কীভাবে খুঁজে পাবেন?


207

কীভাবে কেউ জাভাতে প্রদত্ত শ্রেণীর (বা প্রদত্ত ইন্টারফেসের সমস্ত বাস্তবায়নকারী) সমস্ত সাবক্লাস খুঁজে পাওয়ার চেষ্টা করে? এখন পর্যন্ত, আমার এটি করার একটি পদ্ধতি রয়েছে তবে আমি এটিকে বেশ অদক্ষ মনে করি (কমপক্ষে বলতে গেলে)। পদ্ধতিটি হ'ল:

  1. শ্রেণীর পথে বিদ্যমান সমস্ত শ্রেণীর নামের একটি তালিকা পান
  2. প্রতিটি শ্রেণি লোড করুন এবং এটি পছন্দসই শ্রেণি বা ইন্টারফেসের সাবক্লাস বা বাস্তবায়নকারী কিনা তা পরীক্ষা করুন

Eclipse এ, টাইপ হায়ারার্কি নামে একটি দুর্দান্ত বৈশিষ্ট্য রয়েছে যা এটিকে বেশ দক্ষতার সাথে দেখাতে পরিচালিত করে। কীভাবে কেউ প্রোগ্রামটিভ করে এবং কীভাবে এটি করে?


1
যদিও প্রতিচ্ছবি এবং বসন্তের উপর ভিত্তি করে সমাধানটি আকর্ষণীয় দেখায়, আমার এমন কিছু সহজ সমাধানের প্রয়োজন ছিল যার নির্ভরতা ছিল না। দেখে মনে হচ্ছে আমার আসল কোডটি (কিছু টুইট সহ) যাওয়ার উপায় ছিল।
অ্যাভ্রাম

1
নিশ্চয়ই আপনি getSupeClass পদ্ধতি পুনরাবৃত্তভাবে ব্যবহার করতে পারেন?

আমি নির্দিষ্টভাবে একটি প্রদত্ত শ্রেণীর সমস্ত উপশ্রেণীর সন্ধান করছিলাম । getSuperClass আপনাকে কোন ক্লাসের কী সাবক্লাস রয়েছে তা বলবে না, কেবলমাত্র একটি নির্দিষ্ট সাবক্লাসের জন্য তাত্ক্ষণিক সুপার ক্লাস পান। এছাড়াও, ক্লাসে অ্যাসাইনএবলফ্রমে পদ্ধতিটি আপনার পরামর্শ অনুসারে (পুনরাবৃত্তির প্রয়োজন নেই) এর জন্য আরও উপযুক্ত।
এভ্রোম

এই প্রশ্নটি অন্য অনেক নকল থেকে লিঙ্ক করা হয়েছে তবে এতে কোনও কার্যকর, সাধারণ জাভা উত্তর নেই contain দীর্ঘশ্বাস
ত্যাগ করুন

উত্তর:


77

আপনি যা বর্ণনা করেছেন তা ছাড়া এটি করার কোনও উপায় নেই। এটি সম্পর্কে চিন্তা করুন - ক্লাসপাঠে প্রতিটি ক্লাস স্ক্যান না করে কী কী ক্লাস ক্লাসএক্স বাড়ায় তা কীভাবে জানতে পারে?

গ্রহন কেবলমাত্র সুপার এবং সাবক্লাস সম্পর্কে জানাতে পারে যা "দক্ষ" পরিমাণ বলে মনে হয় কারণ এর মধ্যে ইতিমধ্যে এমন সমস্ত ধরণের ডেটা লোড করা হয়েছে যেখানে আপনি "টাইপ ইন টাইপ হায়ারার্কি" বোতাম টিপেন (যেহেতু এটি ক্রমাগত আপনার ক্লাসগুলি সংকলন করে, ক্লাসপথের সবকিছু সম্পর্কে জানে) ইত্যাদি।


23
Org.refferences নামে একটি সাধারণ গ্রন্থাগার রয়েছে যা এটি এবং অন্যান্য সাধারণ প্রতিচ্ছবি কার্যগুলিতে সহায়তা করে। এই লাইব্রেরির মাধ্যমে আপনি কেবল reflections.getSubTypesOf(aClazz)) লিঙ্কটি
এনওয়ায়ার্ড

@ ম্যাট বি - এটি যদি সমস্ত ক্লাস স্ক্যান করতে হয় তবে এর অর্থ কি এই যে আপনার প্রকল্পে প্রচুর ক্লাস করার সময় একটি পারফরম্যান্স ক্ষয় হয়, যদিও এর মধ্যে খুব কম লোকই আপনার শ্রেণি উপ-শ্রেণিবদ্ধ করছে?
লেটেক্স

যথাযথভাবে। এটি কেবল সমস্ত ক্লাসকে স্পর্শ করে। আপনি নিজের স্ক্যানারটি সংজ্ঞায়িত করতে পারেন আপনি এটির গতি বাড়িয়ে দিতে পারবেন যেমন নির্দিষ্ট প্যাকেজগুলি বাদ দিয়ে আপনি জানেন যে আপনার ক্লাসটি বাড়ানো হবে না বা কেবল ক্লাস ফাইলটি খুলুন এবং ক্লাসের ধ্রুবক বিভাগে ক্লাসের নাম সন্ধানের জন্য পরীক্ষা করুন যাতে প্রতিচ্ছবি স্ক্যানারটি পড়তে না দেয় a ক্লাস সম্পর্কে আরও অনেক তথ্য যা আপনার (প্রত্যক্ষ) সুপার ক্লাসের প্রয়োজনীয় রেফারেন্স অন্তর্ভুক্ত নয় অপ্রত্যক্ষভাবে আপনাকে আরও স্ক্যান করতে হবে। এই মুহূর্তে আছে তাই এটি সেরা।
মার্টিন কার্স্টেন

Fforw দ্বারা উত্তরটি আমার পক্ষে কাজ করেছে এবং সঠিক উত্তর হিসাবে চিহ্নিত করা উচিত। ক্লাসপথ স্ক্যানিংয়ের মাধ্যমে স্পষ্টতই এটি সম্ভব।
ফররুখ নাজমি

আপনি ভুল, বার্নিংওয়েভ লাইব্রেরি সম্পর্কে নীচের প্রতিক্রিয়াটি দেখুন

127

খাঁটি জাভা দিয়ে ক্লাসগুলির জন্য স্ক্যান করা সহজ নয়।

বসন্ত কাঠামোটি ক্লাসপ্যাথস্ক্যানিংক্যান্ডিডেট কম্পোনেন্টপ্রোভিডার নামে একটি শ্রেণীর প্রস্তাব দেয় যা আপনার যা প্রয়োজন তা করতে পারে। 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
ডিফল্ট ফিল্টারগুলি অক্ষম করতে ক্লাসপ্যাথস্ক্যানিংক্যান্ডিডেট কম্পোনেন্টপ্রোভিডার তৈরি করার সময় মিথ্যাটিকে প্যারামিটার হিসাবে পাস করতে হবে। ডিফল্ট ফিল্টারগুলি অন্যান্য ধরণের শ্রেণীর সাথে মেলে, যেমন @ কম্পোমেন্টের সাথে টীকাযুক্ত কিছু anything আমরা কেবল এখানে AssignableTypeFilter সক্রিয় থাকতে চাই।
এমসিডিএস

আপনি বলছেন এটি সহজ নয়, তবে আমরা যদি এটি খাঁটি জাভা দিয়ে করতে চাইতাম তবে কীভাবে করব?
অ্যাকুইটাস

49

কেবল বিল্ট-ইন জাভা রিফ্লেকশন API ব্যবহার করে এটি করা সম্ভব নয়।

এমন একটি প্রকল্প উপস্থিত রয়েছে যা আপনার ক্লাসপাথের প্রয়োজনীয় স্ক্যানিং এবং সূচীকরণ করে যাতে আপনি এই তথ্যটি অ্যাক্সেস করতে পারবেন ...

ভাবনা

স্ক্যানোটেশনের আত্মায় একটি জাভা রানটাইম মেটাডেটা বিশ্লেষণ

প্রতিচ্ছবিগুলি আপনার ক্লাসপাথটিকে স্ক্যান করে, মেটাডেটা সূচী করে, আপনাকে রানটাইমে এটি অনুসন্ধানের অনুমতি দেয় এবং আপনার প্রকল্পের মধ্যে অনেকগুলি মডিউলগুলির জন্য তথ্যটি সংরক্ষণ এবং সংগ্রহ করতে পারে।

প্রতিচ্ছবি ব্যবহার করে আপনি এর জন্য আপনার মেটাডেটাটি জিজ্ঞাসা করতে পারেন:

  • কিছু ধরণের সমস্ত উপপ্রকার পাবেন
  • কিছু টিকা দিয়ে সমস্ত ধরণের টীকাগুলি পান
  • টীকাগুলির সাথে পরামিতিগুলির ম্যাচিং সহ কয়েকটি ধরণের টিকা দিয়ে সমস্ত ধরণের টীকাগুলি পান
  • সমস্ত পদ্ধতি কিছু দিয়ে টীকাগুলি পান

(অস্বীকৃতি: আমি এটি ব্যবহার করি নি, তবে প্রকল্পের বিবরণটি আপনার প্রয়োজনের জন্য যথাযথ মাপসই বলে মনে হচ্ছে))


1
মজাদার. প্রকল্পটিতে কিছু নির্ভরশীলতা রয়েছে যা তাদের ডকুমেন্টেশনের উল্লেখ বলে মনে হচ্ছে না। যেমন (বেশী আমি এতদূর পাওয়া): javaassist, log4J, XStream
Avrom

3
আমি এই প্রকল্পটি মাভেনের সাথে অন্তর্ভুক্ত করেছি এবং এটি দুর্দান্ত কাজ করেছে। সাবক্লাসগুলি পাওয়া প্রথম উত্সের কোড উদাহরণ এবং এটি দুটি লাইন দীর্ঘ :-)
কার্লসফ্রেন্ড

এটি কি কেবল অন্তর্নির্মিত জাভা রিফ্লেকশন এপিআই ব্যবহার করা বা এটি করার পক্ষে খুব অসুবিধাজনক নয়?
ফ্লো

1
আপনি যখন প্রতিচ্ছবি ব্যবহার করতে যাচ্ছেন তখন সাবধান হন এবং তারপরে আপনার অ্যাপ্লিকেশন ওয়ারকে গ্লাস ফিশে স্থাপন করুন! পেয়ারা লাইব্রেরিতে একটি বিরোধ রয়েছে এবং সিডিআই মোতায়েনের ব্যর্থতার সাথে মোতায়েন ব্যর্থ হবে: ওয়েল্ড -001408 - আরও তথ্যের জন্য দয়া করে GLASSFISH-20579 দেখুন। ফাস্টক্লাসপ্যাথস্ক্যানার এই ক্ষেত্রে একটি সমাধান।
lu_ko

আমি এই প্রকল্পটি চেষ্টা করি এবং এটি কার্যকর হয়। আমি কেবল কৌশল ডিজাইনের ধরণটি উন্নত করতে এবং সমস্ত কৌশল কংক্রিটের ক্লাস (সাবক্লাস) পেতে ডেমো উত্তরটি ভাগ করব use
জিন মেং

10

ভুলে যাবেন না যে কোনও শ্রেণীর জন্য উত্পন্ন জাভাদোকের মধ্যে পরিচিত সাবক্লাসগুলির একটি তালিকা অন্তর্ভুক্ত থাকবে (এবং ইন্টারফেসের জন্য, পরিচিত বাস্তবায়নকারী ক্লাসগুলি)।


3
এটি সম্পূর্ণরূপে ভুল, সুপার ক্লাসটি তাদের সাব ক্লাসগুলির উপর নির্ভর করে না, এমনকি জাভাদোক বা মন্তব্যেও নয়।
শিকারি

@ হান্টার আমি একমত নই এটি পুরোপুরি সঠিক যে জাভাডকের মধ্যে পরিচিত সাবক্লাসগুলির একটি তালিকা রয়েছে । অবশ্যই, "পরিচিত" আপনি যে শ্রেণীর সন্ধান করছেন তা অন্তর্ভুক্ত নাও হতে পারে তবে কিছু ব্যবহারের ক্ষেত্রে এটি যথেষ্ট হবে।
Qw3ry

এবং আপনি যে কোনও ক্ষেত্রে কিছু ক্লাস মিস করতে পারেন: আমি ক্লাসপথে একটি নতুন জার লোড করতে পারি (রানটাইম চলাকালীন) এবং এর আগে ঘটে যাওয়া প্রতিটি সনাক্তকরণ ব্যর্থ হবে।
Qw3ry

10

ক্লাসগ্রাফ চেষ্টা করুন । (অস্বীকৃতি, আমি লেখক) ক্লাসগ্রাফ রানটাইম বা বিল্ড টাইমে, তবে আরও অনেক কিছু প্রদত্ত শ্রেণীর সাবক্লাসগুলির জন্য স্ক্যানিং সমর্থন করে। ক্লাসগ্রাফ ক্লাসপথের সমস্ত শ্রেণীর জন্য বা শ্বেত তালিকাভুক্ত প্যাকেজগুলির ক্লাসগুলির জন্য মেমরিতে পুরো শ্রেণি গ্রাফের (সমস্ত শ্রেণি, টীকা, পদ্ধতি, পদ্ধতির প্যারামিটার এবং ক্ষেত্রগুলি) একটি বিমূর্ত উপস্থাপনা তৈরি করতে পারে এবং তবে আপনি এই শ্রেণীর গ্রাফটি জিজ্ঞাসা করতে পারেন তুমি চাও. ক্লাসগ্রাফ অন্য কোনও স্ক্যানারের চেয়ে ক্লাসপথ স্পেসিফিকেশন মেকানিজম এবং ক্লাসলোডারকে সমর্থন করে এবং নতুন জেপিএমএস মডিউল সিস্টেমের সাথে নির্বিঘ্নে কাজ করে, সুতরাং আপনি যদি ক্লাসগ্রাফে আপনার কোডটি বেস করেন তবে আপনার কোড সর্বাধিক বহনযোগ্য। এখানে এপিআই দেখুন।


9

আমি কয়েক বছর আগে এটি করেছি। এটি করার সবচেয়ে নির্ভরযোগ্য উপায় (যেমন অফিশিয়াল জাভা এপিআই এবং কোনও বহিরাগত নির্ভরতা সহ নয়) হ'ল রানটাইম পড়তে পারে এমন একটি তালিকা তৈরি করার জন্য একটি কাস্টম ডকলেট লিখতে write

আপনি এটি কমান্ড লাইন থেকে এটি চালাতে পারেন:

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

আমি জানি আমি এই পার্টিতে কয়েক বছর দেরি করেছি, তবে একই সমস্যাটি সমাধান করার চেষ্টা করে আমি এই প্রশ্নটি এসেছি। ইন্টারফেস প্রয়োগকারী ক্লাসগুলি সন্ধানের জন্য আপনি যদি একটি Elpipse Plugin লিখেছেন (এবং এভাবে তাদের ক্যাচিংয়ের সুবিধা গ্রহণ করুন), তবে আপনি Eclipse এর অভ্যন্তরীণ অনুসন্ধানটি প্রোগ্রামক্রমে ব্যবহার করতে পারেন। এখানে আমার (খুব রুক্ষ) প্রথম কাটা:

  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
অথবা, দেখা যাচ্ছে যে আপনাকে নিজের অনুসন্ধান করতে হবে না। আপনি কেবলমাত্র এটি টাইপহাইরার্কি () এ কল করে আপনার আইটি টাইপ থেকে সরাসরি একটি আইটি টাইপ হায়ারার্কি পেতে পারেন: dev.eclipse.org/newslists/news.eclipse.tools.jdt/msg05036.html
কার্টিস

7

অন্যান্য উত্তরেPojoClassFactory উল্লিখিত সীমাবদ্ধতার কথা মাথায় রেখে আপনি নিম্নলিখিত পদ্ধতিতে ওপেনপোজো ( মাভেনে উপলব্ধ ) ব্যবহার করতে পারেন :

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

কোথায় packageRootপ্যাকেজ আপনি (যেমন অনুসন্ধান করতে ইচ্ছুক রুট স্ট্রিং "com.mycompany"বা এমনকি মাত্র "com"), এবং Superclassআপনার supertype (পাশাপাশি ইন্টারফেসগুলি এই কাজ) হয়।


প্রস্তাবিতগুলির দ্বারা এখন পর্যন্ত দ্রুত এবং সর্বাধিক মার্জিত সমাধান।
কিডক্রিপলার

4

আমি org.reflections.Reflectionsবিমূর্ত শ্রেণীর সাবক্লাসগুলি পেতে ব্যবহার করার জন্য একটি সাধারণ ডেমো লিখি :

https://github.com/xmeng1/ReflectionsDemo


যদিও আপনি এখানে খনন করার জন্য অনেক ক্লাসের লিঙ্কের চেয়ে কোড স্যাম্পল পোস্ট করেন তবে এটি আরও উত্পাদনশীল হবে।
জেসিবয়েড

4

আপনার নির্দিষ্ট প্রয়োজনীয়তার উপর নির্ভর করে, কিছু ক্ষেত্রে জাভার পরিষেবা লোডার প্রক্রিয়া আপনার পরে যা অর্জন করতে পারে।

সংক্ষেপে, এটি বিকাশকারীদের স্পষ্টভাবে ঘোষণা করতে দেয় যে একটি শ্রেণি সাব-ক্লাস করে কিছু অন্যান্য শ্রেণি (বা কিছু ইন্টারফেস প্রয়োগ করে) JAR / WAR ফাইল META-INF/servicesডিরেক্টরিতে একটি ফাইলে তালিকাভুক্ত করে । এরপরে java.util.ServiceLoaderশ্রেণীর সাহায্যে এটি আবিষ্কার করা যেতে পারে যা কোনও Classবস্তু দেওয়া হলে 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একটি বাস্তবায়ন Exampleএকটি ফাইল তৈরি করে META-INF/services/com.example.Exampleপাঠ্য ধারণকারী com.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

আপনি আপনার প্রয়োগ এবং Eclipse এর মধ্যে পার্থক্য দেখানোর কারণ হ'ল আপনি প্রতিবার স্ক্যান করেন, যখন Eclipse (এবং অন্যান্য সরঞ্জাম) কেবল একবার স্ক্যান করে (বেশিরভাগ সময় প্রকল্পের বোঝার সময়) এবং একটি সূচক তৈরি করে। পরের বার আপনি ডেটা জিজ্ঞাসা করুন এটি আবার স্ক্যান করে না, তবে সূচীটি দেখুন।


3

আমি একটি প্রতিচ্ছবি লিবি ব্যবহার করছি, যা আপনার সাবক্লাসের জন্য আপনার ক্লাসপথটি স্ক্যান করে: https://github.com/ronmamo/refferences

এটি এটি করা হবে:

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

2

এগুলিকে (this.getClass ()। GetName ()) প্যারেন্ট ক্লাস কনস্ট্রাক্টর (বা একটি ডিফল্ট তৈরি করুন) এর ভিতরে একটি স্থিতিশীল মানচিত্রে যুক্ত করুন তবে এটি রানটাইমে আপডেট হবে। অলস সূচনা যদি কোনও বিকল্প হয় তবে আপনি এই পদ্ধতির চেষ্টা করতে পারেন।


1

আপনি org.refferences গ্রন্থাগার ব্যবহার করতে পারেন এবং তারপরে, প্রতিচ্ছবি শ্রেণীর একটি অবজেক্ট তৈরি করতে পারেন। এই অবজেক্টটি ব্যবহার করে, আপনি প্রদত্ত শ্রেণীর সমস্ত সাবক্লাসের তালিকা পেতে পারেন। 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());
        }
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.