রানটাইমের সময়, জাভা অ্যাপ্লিকেশনটিতে এমন সমস্ত ক্লাস সন্ধান করুন যা বেস ক্লাসটি প্রসারিত করে


147

আমি এরকম কিছু করতে চাই:

List<Animal> animals = new ArrayList<Animal>();

for( Class c: list_of_all_classes_available_to_my_app() )
   if (c is Animal)
      animals.add( new c() );

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

List<Animal> animals = new ArrayList<Animal>();
animals.add( new Dog() );
animals.add( new Cat() );
animals.add( new Donkey() );
...

উপরোক্ত পদ্ধতির সাহায্যে আমি কেবলমাত্র একটি নতুন ক্লাস তৈরি করতে পারি যা অ্যানিমাল প্রসারিত করে এবং এটি স্বয়ংক্রিয়ভাবে উঠতে পারে।

আপডেট: 10/16/2008 9:00 am প্যাসিফিক স্ট্যান্ডার্ড সময়:

এই প্রশ্নটি অনেক দুর্দান্ত প্রতিক্রিয়া তৈরি করেছে - আপনাকে ধন্যবাদ। প্রতিক্রিয়া এবং আমার গবেষণা থেকে, আমি খুঁজে পেয়েছি যে আমি যা করতে চাই তা জাভার অধীনে সম্ভব নয়। এমন পদ্ধতি রয়েছে যেমন ডিডিমিট্রভের সার্ভিস লোডার প্রক্রিয়া যা কাজ করতে পারে - তবে আমি যা চাই তার জন্য এগুলি অত্যন্ত ভারী এবং আমি বিশ্বাস করি যে আমি জাভা কোড থেকে কোনও সমস্যাটি কেবল একটি বাহ্যিক কনফিগারেশন ফাইলে সরিয়ে নিয়েছি। 5/10/19 আপডেট করুন (11 বছর পরে!) এখন অনেকগুলি লাইব্রেরি রয়েছে যা @ ইভাননিকের উত্তর অনুসারে এর সাথে সহায়তা করতে পারে org.refferences ভাল দেখাচ্ছে। এছাড়াও ClassGraph @Luke হাচিসন থেকে উত্তর দেখতে ভালই লাগছে। উত্তরের পাশাপাশি আরও বেশ কয়েকটি সম্ভাবনা রয়েছে।

আমি যা চাই তা জানার আর একটি উপায়: আমার অ্যানিম্যাল ক্লাসে একটি স্ট্যাটিক ফাংশন এমন সব শ্রেণীর সন্ধান করে এবং তা ইনস্ট্যান্ট করে যা কোনও পরবর্তী কনফিগারেশন / কোডিং ছাড়াই। আমার যদি কনফিগার করতে হয় তবে আমি তাদের পাশাপাশি কেবলমাত্র প্রাণী ক্লাসে ইনস্ট্যান্ট করতে পারি। আমি বুঝতে পেরেছি যে একটি জাভা প্রোগ্রামটি কেবল ক্লাস ফাইলগুলির একটি looseিলে .ালা ফেডারেশন।

মজার বিষয় হল এটি সি # তে মোটামুটি তুচ্ছ


1
কিছুক্ষণ অনুসন্ধানের পরে, মনে হচ্ছে জাভাতে ফাটানো এটি একটি কঠিন বাদাম। এখানে একটি থ্রেড রয়েছে যার কিছু তথ্য রয়েছে: forums.sun.com/thread.jspa?threadID=341935&start=15 এর বাস্তবায়ন আমার প্রয়োজনের চেয়ে বেশি, আমি অনুমান করি আমি আপাতত দ্বিতীয় বাস্তবায়নটি ধরে রেখেছি।
জনিলম্বদা 17

এটি একটি উত্তর হিসাবে রাখুন এবং পাঠকদের এটিতে ভোট দিন
ভোনসি

3
সি # তে এটি করার লিঙ্কটি বিশেষ কিছু দেখায় না। এসি # এসেম্বলি জাভা জেআর ফাইলের সমতুল্য। এটি সংকলিত শ্রেণিবদ্ধ ফাইল (এবং সংস্থানসমূহ) এর সংগ্রহ। লিঙ্কটি দেখায় যে কীভাবে একটি একক সমাবেশ থেকে ক্লাসগুলি বের করা যায়। আপনি এটি জাভা দিয়ে প্রায় সহজেই করতে পারেন। আপনার জন্য সমস্যাটি হ'ল আপনাকে সমস্ত জেআর ফাইল এবং প্রকৃত আলগা ফাইলগুলি (ডিরেক্টরিগুলি) দেখতে হবে; নেট। (কোনও ধরণের বা বিভিন্ন ধরণের একটি PATH অনুসন্ধান করুন) দিয়ে আপনার একই কাজ করা দরকার।
কেভিন ব্রক

উত্তর:


156

আমি org.refferences ব্যবহার করি :

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);

আরেকটি উদাহরণ:

public static void main(String[] args) throws IllegalAccessException, InstantiationException {
    Reflections reflections = new Reflections("java.util");
    Set<Class<? extends List>> classes = reflections.getSubTypesOf(java.util.List.class);
    for (Class<? extends List> aClass : classes) {
        System.out.println(aClass.getName());
        if(aClass == ArrayList.class) {
            List list = aClass.newInstance();
            list.add("test");
            System.out.println(list.getClass().getName() + ": " + list.size());
        }
    }
}

6
Org.refferences সম্পর্কে লিঙ্কের জন্য ধন্যবাদ। আমি ভুল করে বুঝতে পেরেছিলাম যে এটি যতটা সহজ হবে ঠিক ততটাই সহজ the
আকাদমাদ

1
দুর্দান্ত প্যাকেজ "org.reflections" এর এই সহায়ক লিঙ্কটির জন্য আপনাকে ধন্যবাদ! এর সাথে আমি শেষ পর্যন্ত আমার সমস্যার জন্য একটি ব্যবহারিক এবং ঝরঝরে সমাধান পেয়েছি।
হার্টমুট পি

3
কোনও নির্দিষ্ট প্যাকেজটি লক্ষ্য না করে, সমস্ত উপলব্ধ ক্লাস লোড না করে সমস্ত প্রতিচ্ছবি পাওয়ার কোনও উপায় আছে কি?
জোয় বারুচ

মনে রাখবেন যে ক্লাসগুলি সন্ধান করা তাদের তাত্ক্ষণিকভাবে আপনার সমস্যার সমাধান করবে না ( animals.add( new c() );আপনার কোডের লাইন 5 ) কারণ Class.newInstance()উপস্থিত থাকার পরেও আপনার কোনও গ্যারান্টি নেই যে নির্দিষ্ট শ্রেণিতে একটি প্যারামিটারলেস কনস্ট্রাক্টর রয়েছে (সি # আপনাকে জেনেরিকের প্রয়োজনের অনুমতি দেয়)
usr-local-ΕΨΗΕΛΩΝ

ক্লাসগ্রাফও দেখুন: github.com / ক্লাসগ্রাফ / ক্লাসগ্রাফ (দাবি অস্বীকার , আমি লেখক)। আমি একটি পৃথক উত্তরে একটি কোড উদাহরণ দেব।
লুক হাচিসন

34

আপনি যা চান তা করার জাভা উপায় হ'ল সার্ভিস লোডার প্রক্রিয়াটি ব্যবহার করা ।

এছাড়াও অনেকগুলি পরিচিত ক্লাসপথ লোকেশন (যেমন /META-INF/services/myplugin.properties) এ একটি ফাইল রেখে এবং তারপরে ClassLoader.getResource () ব্যবহার করে সমস্ত জার থেকে এই নামের সাথে সমস্ত ফাইল গণনা করে their এটি প্রতিটি জারকে তার নিজস্ব সরবরাহকারী রফতানি করতে দেয় এবং আপনি Class.forName () ব্যবহার করে প্রতিবিম্ব দ্বারা তাদের ইনস্ট্যান্ট করতে পারেন)


1
ক্লাসে টীকাগুলির উপর ভিত্তি করে মেটা-আইএনএফ পরিষেবাদি ফাইলটি সহজেই উত্পন্ন করার জন্য, আপনি পরীক্ষা করতে পারেন: metainf-services.kohsuke.org বা কোড. google.com/p/spi
এলেক

Bleah। কেবল জটিলতার মাত্রা যুক্ত করে, তবে উভয়ই একটি শ্রেণি তৈরি করার প্রয়োজনীয়তা দূর করে না এবং এরপরে এটি খুব দূরের কোনও দেশে নিবন্ধভুক্ত করে।
কেভিন cline

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

4
প্রকৃতপক্ষে, যদি আপনার এক ধরণের কার্যক্ষম সমাধানের প্রয়োজন হয় তবে প্রতিচ্ছবি / স্ক্যানোটেশনগুলি একটি ভাল বিকল্প, তবুও উভয়ই একটি বাহ্যিক নির্ভরতা চাপিয়ে দেয়, অ-বিবাদী এবং জাভা সম্প্রদায় প্রক্রিয়া দ্বারা সমর্থনযোগ্য নয়। তদ্ব্যতীত, আমি হাইলাইট করতে চেয়েছিলাম যে আপনি কোনও ইন্টারফেস বাস্তবায়িতভাবে সমস্ত ক্লাস কখনই নির্ভরযোগ্যভাবে পেতে পারবেন না, যেহেতু যে কোনও সময় পাতলা বাতাসের বাইরে কোনও নতুন তৈরি করা তুচ্ছ। এর সমস্ত ওয়ার্টগুলির জন্য, জাভার পরিষেবা লোডার বোঝা এবং ব্যবহার করা সহজ। আমি বিভিন্ন কারণে এর থেকে দূরে থাকতে হবে, কিন্তু তারপর ক্লাসপাথ স্ক্যানিং এমনকি খারাপ হল: stackoverflow.com/a/7237152/18187
ddimitrov

11

একটি দিক ভিত্তিক দৃষ্টিভঙ্গি থেকে এ সম্পর্কে চিন্তা করুন; আপনি কী করতে চান, রানটাইমের সময় সমস্ত ক্লাসগুলিই জানেন যে এটি অ্যানিম্যাল ক্লাসটি বাড়িয়েছে। (আমি মনে করি এটি আপনার শিরোনামের তুলনায় আপনার সমস্যার কিছুটা সঠিক বর্ণনা; অন্যথায়, আমি মনে করি না যে আপনার রানটাইম প্রশ্ন আছে।)

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

সুতরাং, মোটামুটি;

public abstract class Animal
    {
    private static ArrayList<Class> instantiatedDerivedTypes;
    public Animal() {
        Class derivedClass = this.getClass();
        if (!instantiatedDerivedClass.contains(derivedClass)) {
            instantiatedDerivedClass.Add(derivedClass);
        }
    }

অবশ্যই, ইনস্ট্যান্টিয়েটেডডেরিভড ক্লাস শুরু করার জন্য আপনাকে অ্যানিম্যাল এ স্ট্যাটিক কনস্ট্রাক্টরের দরকার হবে ... আমি মনে করি এটি আপনি যা চান সম্ভবত তা করবে'll মনে রাখবেন যে এটি কার্যকরকরণের পথে নির্ভর করে; আপনার যদি কুকুর শ্রেণি থাকে যা প্রাণীর কাছ থেকে উদ্ভূত হয় যা কখনই ডাকা হয় না, আপনার পশুর শ্রেণির তালিকায় এটি থাকবে না।


6

দুর্ভাগ্যক্রমে এটি সম্পূর্ণরূপে সম্ভব নয় কারণ ClassLoader আপনাকে কোন ক্লাসগুলি উপলভ্য তা বলে দেয় না। আপনি তবে এরকম কিছু করতে মোটামুটি কাছাকাছি যেতে পারেন:

for (String classpathEntry : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) {
    if (classpathEntry.endsWith(".jar")) {
        File jar = new File(classpathEntry);

        JarInputStream is = new JarInputStream(new FileInputStream(jar));

        JarEntry entry;
        while( (entry = is.getNextJarEntry()) != null) {
            if(entry.getName().endsWith(".class")) {
                // Class.forName(entry.getName()) and check
                //   for implementation of the interface
            }
        }
    }
}

সম্পাদনা করুন: জনস্টক সঠিক (মন্তব্যে) যে এটি কেবল স্ট্যান্ডলোন জাভা অ্যাপ্লিকেশনগুলির জন্য কাজ করে এবং কোনও অ্যাপ্লিকেশন সার্ভারের আওতায় কাজ করবে না।


ক্লাসগুলি অন্য উপায়ে লোড করা হলে এটি ভাল কাজ করে না, উদাহরণস্বরূপ, ওয়েব বা জে 2 ই ই ধারক মধ্যে।
জনস্টক

আপনি URL[]ক্লাসলুডার শ্রেণিবিন্যাস থেকে যদি পথগুলি (প্রায়শই তবে সর্বদা এটি সম্ভব নাও হয়) অনুসন্ধান করেন তবে আপনি সম্ভবত আরও ভাল একটি কাজ করতে পারেন under প্রায়শই যদিও আপনার অবশ্যই অনুমতি থাকতে হবে সাধারণত SecurityManagerজেভিএম-এর মধ্যে আপনার বোঝা থাকবে ।
কেভিন ব্রক

আমার জন্য একটি কবজ মত কাজ! আমি আশঙ্কা করেছি যে এটি ভারী ওজন এবং ধীর গতির হতে পারে, ক্লাসপথের সমস্ত শ্রেণীর মধ্য দিয়ে যাওয়া, তবে আসলে আমি "-ejb-" বা অন্যান্য স্বীকৃত ফাইলের নাম থাকা ফাইলগুলিতে যাচাই করেছিলাম সেগুলি সীমাবদ্ধ করেছিলাম এবং এটি আরম্ভের চেয়ে এখনও 100 গুণ বেশি দ্রুত এম্বেড করা গ্লাসফিশ বা ইজেবিসিটিটেনার। আমার বিশেষ পরিস্থিতিতে আমি তখন "স্টেটলেস", "স্টেটফুল" এবং "সিঙ্গেলটন" টীকাগুলি সন্ধানকারী ক্লাসগুলি বিশ্লেষণ করেছি এবং যদি সেগুলি দেখি তবে আমি জেএনডিআই ম্যাপযুক্ত নামটি আমার মকআইনিটিয়ালকন্টেক্সট্যাক্টরিতে যুক্ত করেছি। আবার ধন্যবাদ!
cs94njw

4

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

এখানে ক্লাসের কোনওটি লোড না করা একটি সাধারণ উদাহরণ:

package test;

import java.util.Set;
import net.sourceforge.stripes.util.ResolverUtil;

public class BaseClassTest {
    public static void main(String[] args) throws Exception {
        ResolverUtil<Animal> resolver = new ResolverUtil<Animal>();
        resolver.findImplementations(Animal.class, "test");
        Set<Class<? extends Animal>> classes = resolver.getClasses();

        for (Class<? extends Animal> clazz : classes) {
            System.out.println(clazz);
        }
    }
}

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}

এটি একটি অ্যাপ্লিকেশন সার্ভারেও কাজ করে যেহেতু এটি কাজ করার জন্য তৈরি করা হয়েছিল;)

কোডটি মূলত নিম্নলিখিতটি করে:

  • আপনার নির্দিষ্ট করা প্যাকেজগুলির সমস্ত সংস্থান পুনরুক্ত করুন rate
  • কেবলমাত্র ক্লাসে শেষ হওয়া সংস্থানগুলি রাখুন
  • এই ক্লাসগুলি ব্যবহার করে লোড করুন ClassLoader#loadClass(String fullyQualifiedName)
  • যদি চেক করে Animal.class.isAssignableFrom(loadedClass);

4

প্রদত্ত শ্রেণীর সমস্ত সাবক্লাস তালিকাভুক্ত করার জন্য সবচেয়ে শক্তিশালী প্রক্রিয়াটি বর্তমানে ক্লাসগ্রাফ , কারণ এটি নতুন জেপিএমএস মডিউল সিস্টেম সহ শ্রেণিপথ স্পেসিফিকেশন ব্যবস্থার বিস্তৃত সম্ভাব্য অ্যারে পরিচালনা করে । (আমি লেখক।)

List<Class<Animal>> animals;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("com.zoo.animals")
        .enableClassInfo().scan()) {
    animals = scanResult
        .getSubclasses(Animal.class.getName())
        .loadClasses(Animal.class);
}

ফলাফল তালিকার তালিকার <ক্লাস <
অ্যানিমাল

2

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


2

এটা ব্যবহার কর

public static Set<Class> getExtendedClasses(Class superClass)
{
    try
    {
        ResolverUtil resolver = new ResolverUtil();
        resolver.findImplementations(superClass, superClass.getPackage().getName());
        return resolver.getClasses();  
    }
    catch(Exception e)
    {Log.d("Log:", " Err: getExtendedClasses() ");}

    return null;
}

getExtendedClasses(Animals.class);

সম্পাদনা:


2
রেজোলভারটিল সম্পর্কে আপনাকে আরও কিছু বলতে হবে। এটা কি? এটি কোন গ্রন্থাগার থেকে আসে?
জনিলম্বদা

1

যারা এই প্রশ্নের উত্তর দিয়েছেন তাদের সবাইকে ধন্যবাদ।

দেখে মনে হচ্ছে এটি ক্র্যাক করার পক্ষে একটি শক্ত বাদাম। আমি ছেড়ে দিয়ে এবং আমার বেসক্লাসে একটি স্ট্যাটিক অ্যারে এবং গেটর তৈরি করে শেষ করেছি।

public abstract class Animal{
    private static Animal[] animals= null;
    public static Animal[] getAnimals(){
        if (animals==null){
            animals = new Animal[]{
                new Dog(),
                new Cat(),
                new Lion()
            };
        }
        return animals;
    }
}

দেখে মনে হচ্ছে যে জাভা কেবল সি # এর মতো স্ব-আবিষ্কারের জন্য সেট আপ করা হয়নি। আমি মনে করি সমস্যাটি হ'ল যেহেতু একটি জাভা অ্যাপ্লিকেশনটি কোথাও ডিরেক্টরি / জার ফাইলের বাইরে .class ফাইলগুলির সংগ্রহ, তাই রানটাইমটি কোনও শ্রেণি সম্পর্কে রেফারেন্স না হওয়া পর্যন্ত জানে না। সেই সময়ে লোডার এটি লোড করে - আমি যা করার চেষ্টা করছি সেটি উল্লেখ করার আগে এটি আবিষ্কার করা যা ফাইল সিস্টেমের বাইরে না গিয়ে অনুসন্ধান করা ছাড়া সম্ভব নয়।

আমি সর্বদা এমন কোড পছন্দ করি যা নিজের সম্পর্কে এটি বলার পরিবর্তে নিজেই আবিষ্কার করতে পারে তবে হায় আফসোস এটিও কার্যকর হয়।

আবার ধন্যবাদ!


1
জাভা স্ব-আবিষ্কারের জন্য সেট আপ করা হয়েছে। আপনার আরও কিছুটা কাজ করা দরকার। বিস্তারিত জানার জন্য আমার উত্তর দেখুন।
ডেভ জার্ভিস

1

ওপেনপোজো ব্যবহার করে আপনি নিম্নলিখিতগুলি করতে পারেন:

String package = "com.mycompany";
List<Animal> animals = new ArrayList<Animal>();

for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(package, Animal.class, null) {
  animals.add((Animal) InstanceFactory.getInstance(pojoClass));
}

0

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


0

একটি উপায় হ'ল ক্লাসগুলি একটি স্ট্যাটিক ইনিশিয়ালাইজার ব্যবহার করা ... আমি মনে করি না যে এগুলি উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছে (এটি যদি হয় তবে তা কার্যকর হবে না):

public class Dog extends Animal{

static
{
   Animal a = new Dog();
   //add a to the List
}

এর সাথে জড়িত সমস্ত ক্লাসে আপনার এই কোডটি যুক্ত করা দরকার। তবে এটি কোথাও বড় কুৎসিত লুপ এড়ানো এড়ানো, পশুর বাচ্চাদের সন্ধানের জন্য প্রতিটি শ্রেণীর পরীক্ষা করে।


3
এটি আমার ক্ষেত্রে কাজ করে না। ক্লাসটি কোথাও রেফারেন্সযুক্ত না হওয়ায় এটি কখনই লোড হয় না তাই স্থির আরম্ভকারীকে কখনও ডাকা হয় না। দেখে মনে হচ্ছে ক্লাসটি লোড হওয়ার পরে সমস্ত কিছুর আগে একটি স্ট্যাটিক ইনিশিয়ালাইজার বলা হয় - তবে আমার ক্ষেত্রে ক্লাসটি কখনই লোড হয় না।
জনিলম্বদা

0

আমি প্যাকেজ লেভেল টীকাগুলি ব্যবহার করে এবং তারপর সেই টীকাকে যুক্তি হিসাবে ক্লাসগুলির একটি তালিকা তৈরি করে বেশ দক্ষতার সাথে এই সমস্যার সমাধান করেছি।

একটি ইন্টারফেস প্রয়োগকারী জাভা ক্লাসগুলি সন্ধান করুন

বাস্তবায়নগুলিকে কেবল একটি প্যাকেজ-ইনফো.জাভা তৈরি করতে হবে এবং তারা যে ক্লাসগুলিকে সমর্থন করতে চায় তার তালিকার সাথে ম্যাজিক টীকা যুক্ত করতে হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.