java - আপনি প্রতিফলন ব্যবহার করে একটি প্যাকেজ সব ক্লাস খুঁজে পেতে পারেন?




reflection packages (16)

একটি প্রদত্ত প্যাকেজ সব ক্লাস বা ইন্টারফেস খুঁজে পাওয়া সম্ভব? (দ্রুত Package এ খুঁজছেন, এটি কোন মত মনে হবে।)


বসন্ত

এই উদাহরণটি স্প্রিং 4 এর জন্য, তবে আপনি পূর্ববর্তী সংস্করণগুলিতে ক্লাসপ্যাথ স্ক্যানারটিও খুঁজে পেতে পারেন।

// create scanner and disable default filters (that is the 'false' argument)
final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
// add include filters which matches all the classes (or use your own)
provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*")));

// get matching classes defined in the package
final Set<BeanDefinition> classes = provider.findCandidateComponents("my.package.name");

// this is how you can load the class type from BeanDefinition instance
for (BeanDefinition bean: classes) {
    Class<?> clazz = Class.forName(bean.getBeanClassName());
    // ... do your magic with the class ...
}

গুগল গুয়াভা

দ্রষ্টব্য: সংস্করণ 14 এ, API টি এখনও @ বিটা হিসাবে চিহ্নিত হয়েছে, তাই উৎপাদন কোডে সতর্ক থাকুন।

final ClassLoader loader = Thread.currentThread().getContextClassLoader();

for (final ClassPath.ClassInfo info : ClassPath.from(loader).getTopLevelClasses()) {
  if (info.getName().startsWith("my.package.")) {
    final Class<?> clazz = info.load();
    // do something with your clazz
  }
}

আপনি ClassLoader 1 ClassLoader ব্যবহার করে এই পদ্ধতিটি 1 ব্যবহার করতে পারেন।

/**
 * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
 *
 * @param packageName The base package
 * @return The classes
 * @throws ClassNotFoundException
 * @throws IOException
 */
private static Class[] getClasses(String packageName)
        throws ClassNotFoundException, IOException {
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    assert classLoader != null;
    String path = packageName.replace('.', '/');
    Enumeration<URL> resources = classLoader.getResources(path);
    List<File> dirs = new ArrayList<File>();
    while (resources.hasMoreElements()) {
        URL resource = resources.nextElement();
        dirs.add(new File(resource.getFile()));
    }
    ArrayList<Class> classes = new ArrayList<Class>();
    for (File directory : dirs) {
        classes.addAll(findClasses(directory, packageName));
    }
    return classes.toArray(new Class[classes.size()]);
}

/**
 * Recursive method used to find all classes in a given directory and subdirs.
 *
 * @param directory   The base directory
 * @param packageName The package name for classes found inside the base directory
 * @return The classes
 * @throws ClassNotFoundException
 */
private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
    List<Class> classes = new ArrayList<Class>();
    if (!directory.exists()) {
        return classes;
    }
    File[] files = directory.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            assert !file.getName().contains(".");
            classes.addAll(findClasses(file, packageName + "." + file.getName()));
        } else if (file.getName().endsWith(".class")) {
            classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
        }
    }
    return classes;
}

__________
1 এই পদ্ধতিটি মূলত http://snippets.dzone.com/posts/show/4831 থেকে নেওয়া হয়েছিল, যা বর্তমানে ইন্টারনেট আর্কাইভ দ্বারা সংরক্ষণাগারভুক্ত হয়েছিল। স্নিপেটটি https://dzone.com/articles/get-all-classes-within-package এ উপলব্ধ।


আমি এই সমস্যা সমাধানের জন্য FastClasspathScanner লিখেছেন। এটি বিভিন্ন ধরণের ক্লাসপ্যাথ স্ক্যানিং কাজগুলি পরিচালনা করে, একটি সহজ API রয়েছে, অনেকগুলি ক্লাসলোডার এবং ক্লাসপথ এনভায়রনমেন্টগুলির সাথে কাজ করে, সাবধানে সমান্তরাল করা হয়েছে এবং উচ্চ গতি এবং কম মেমরি খরচ ব্যবহারের জন্য অত্যন্ত অপ্টিমাইজ করা হয়েছে। এটি ক্লাস গ্রাফের গ্রাফভিজ ভিজ্যুয়ালাইজেশন তৈরি করতে পারে, যা দেখায় কিভাবে ক্লাস একে অপরের সাথে সংযুক্ত হয়।

প্রদত্ত প্যাকেজে সমস্ত ক্লাস বা ইন্টারফেস খুঁজে পেতে আপনার আসল প্রশ্নের জন্য, আপনি যা করতে পারেন:

List<String> classNames = new FastClasspathScanner("com.mypackage").scan()
    .getNamesOfAllClasses();

এতে অনেকগুলি সম্ভাব্য রূপ রয়েছে - সম্পূর্ণ তথ্যের জন্য ডকুমেন্টেশন (উপরে লিঙ্কযুক্ত) দেখুন।


আমি এই সমস্যার সমাধান করে একটি সহজ github প্রকল্প একত্র করা:

https://github.com/ddopson/java-class-enumerator

এটি উভয় ফাইল ভিত্তিক ক্লাসপথ এবং জার ফাইলগুলির জন্য কাজ করা উচিত।

প্রকল্পটি পরীক্ষা করার পরে 'মেক' চালানো হলে এটি মুদ্রণ করবে:

 Cleaning...
rm -rf build/
 Building...
javac -d build/classes src/pro/ddopson/ClassEnumerator.java src/test/ClassIShouldFindOne.java src/test/ClassIShouldFindTwo.java src/test/subpkg/ClassIShouldFindThree.java src/test/TestClassEnumeration.java
 Making JAR Files...
jar cf build/ClassEnumerator_test.jar -C build/classes/ . 
jar cf build/ClassEnumerator.jar -C build/classes/ pro
 Running Filesystem Classpath Test...
java -classpath build/classes test.TestClassEnumeration
ClassDiscovery: Package: 'test' becomes Resource: 'file:/Users/Dopson/work/other/java-class-enumeration/build/classes/test'
ClassDiscovery: Reading Directory '/Users/Dopson/work/other/java-class-enumeration/build/classes/test'
ClassDiscovery: FileName 'ClassIShouldFindOne.class'  =>  class 'test.ClassIShouldFindOne'
ClassDiscovery: FileName 'ClassIShouldFindTwo.class'  =>  class 'test.ClassIShouldFindTwo'
ClassDiscovery: FileName 'subpkg'  =>  class 'null'
ClassDiscovery: Reading Directory '/Users/Dopson/work/other/java-class-enumeration/build/classes/test/subpkg'
ClassDiscovery: FileName 'ClassIShouldFindThree.class'  =>  class 'test.subpkg.ClassIShouldFindThree'
ClassDiscovery: FileName 'TestClassEnumeration.class'  =>  class 'test.TestClassEnumeration'
 Running JAR Classpath Test...
java -classpath build/ClassEnumerator_test.jar  test.TestClassEnumeration
ClassDiscovery: Package: 'test' becomes Resource: 'jar:file:/Users/Dopson/work/other/java-class-enumeration/build/ClassEnumerator_test.jar!/test'
ClassDiscovery: Reading JAR file: '/Users/Dopson/work/other/java-class-enumeration/build/ClassEnumerator_test.jar'
ClassDiscovery: JarEntry 'META-INF/'  =>  class 'null'
ClassDiscovery: JarEntry 'META-INF/MANIFEST.MF'  =>  class 'null'
ClassDiscovery: JarEntry 'pro/'  =>  class 'null'
ClassDiscovery: JarEntry 'pro/ddopson/'  =>  class 'null'
ClassDiscovery: JarEntry 'pro/ddopson/ClassEnumerator.class'  =>  class 'null'
ClassDiscovery: JarEntry 'test/'  =>  class 'null'
ClassDiscovery: JarEntry 'test/ClassIShouldFindOne.class'  =>  class 'test.ClassIShouldFindOne'
ClassDiscovery: JarEntry 'test/ClassIShouldFindTwo.class'  =>  class 'test.ClassIShouldFindTwo'
ClassDiscovery: JarEntry 'test/subpkg/'  =>  class 'null'
ClassDiscovery: JarEntry 'test/subpkg/ClassIShouldFindThree.class'  =>  class 'test.subpkg.ClassIShouldFindThree'
ClassDiscovery: JarEntry 'test/TestClassEnumeration.class'  =>  class 'test.TestClassEnumeration'
 Tests Passed. 

আমার অন্যান্য উত্তর দেখুন


কোন অতিরিক্ত লাইব্রেরি ব্যবহার না করে:

package test;

import java.io.DataInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class Test {
    public static void main(String[] args) throws Exception{
        List<Class> classes = getClasses(Test.class.getClassLoader(),"test");
        for(Class c:classes){
            System.out.println("Class: "+c);
        }
    }

    public static List<Class> getClasses(ClassLoader cl,String pack) throws Exception{

        String dottedPackage = pack.replaceAll("[/]", ".");
        List<Class> classes = new ArrayList<Class>();
        URL upackage = cl.getResource(pack);

        DataInputStream dis = new DataInputStream((InputStream) upackage.getContent());
        String line = null;
        while ((line = dis.readLine()) != null) {
            if(line.endsWith(".class")) {
               classes.add(Class.forName(dottedPackage+"."+line.substring(0,line.lastIndexOf('.'))));
            }
        }
        return classes;
    }
}

ক্লাস লোডার গতিশীল প্রকৃতির কারণে, এটি সম্ভব নয়। ক্লাস লোডারগুলিকে এটি সরবরাহ করতে পারে এমন ক্লাসগুলিকে ভিএম বলতে হবে না, পরিবর্তে তারা কেবল ক্লাসের জন্য অনুরোধগুলি হস্তান্তরিত করে এবং একটি ক্লাস ফেরত দিতে বা ব্যতিক্রমটি নিক্ষেপ করতে হয়।

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

যদি এমন ক্লাস থাকে যা উত্পন্ন হয়, অথবা দূরবর্তীভাবে বিতরিত হয় তবে আপনি সেই ক্লাসগুলি আবিষ্কার করতে পারবেন না।

স্বাভাবিক পদ্ধতির পরিবর্তে আপনি যে কোনও শ্রেণীতে অ্যাক্সেসের প্রয়োজন এমন শ্রেণীগুলি নিবন্ধন করতে পারেন, অথবা একটি ভিন্ন শ্রেণিতে তাদের উল্লেখ করতে পারেন। বা শুধুমাত্র নামকরণ আসে যখন কনভেনশন ব্যবহার করুন।

সংযোজন: প্রতিফলন গ্রন্থাগার আপনাকে বর্তমান ক্লাসপথের ক্লাসগুলি দেখতে অনুমতি দেবে। এটি একটি প্যাকেজ মধ্যে সব ক্লাস পেতে ব্যবহার করা যেতে পারে:

 Reflections reflections = new Reflections("my.project.prefix");

 Set<Class<? extends Object>> allClasses = 
     reflections.getSubTypesOf(Object.class);

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

Reflections reflections = new Reflections("my.package");
Set<Class<? extends Object>> classes = reflections.getSubTypesOf(Object.class);

আরেকটি পদ্ধতি হল জাভা প্লাগেবল এনটোটেশন প্রসেসিং এপিআই ব্যবহার করা যা এনটোটেশন প্রসেসর লিখতে পারে যা সমস্ত এনটাইটেড ক্লাসগুলি কম্পাইল সময় সংগ্রহ করবে এবং রানটাইম ব্যবহারের জন্য ইন্ডেক্স ফাইল তৈরি করবে। ClassIndex গ্রন্থাগারে এই প্রক্রিয়াটি প্রয়োগ করা হয়েছে:

// package-info.java
@IndexSubclasses
package my.package;

// your code
Iterable<Class> classes = ClassIndex.getPackageClasses("my.package");

জাভা কম্পাইলার স্বয়ংক্রিয়ভাবে ক্লাসপথের যেকোনো প্রসেসর আবিষ্কার করার জন্য স্ক্যানিং সম্পূর্ণরূপে স্বয়ংক্রিয়ভাবে ধন্যবাদ হিসাবে অতিরিক্ত সেটআপের প্রয়োজন নেই।


হ্যাঁ আপনি কয়েকটি API ব্যবহার করতে পারেন, এখানে আমি কীভাবে এটি পছন্দ করি, এই সমস্যাটির মুখোমুখি হবার যা আমি হাইবারনেট কোর ব্যবহার করেছিলাম এবং কোন নির্দিষ্ট টীকা দিয়ে কথিত যেখানে ক্লাস খুঁজে বের করতে হয়েছিল।

এই কাস্টম টীকাটি তৈরি করুন যা ব্যবহার করে আপনি কোন ক্লাসগুলি বাছাই করতে চান তা চিহ্নিত করুন।

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EntityToBeScanned {

}

তারপর তার সাথে আপনার বর্গ চিহ্নিত করুন

@EntityToBeScanned 
public MyClass{

}

নিম্নলিখিত ইউটিলিটি ক্লাসটি তৈরি করুন যা নিম্নোক্ত পদ্ধতিতে রয়েছে

public class ClassScanner {

    public static Set<Class<?>> allFoundClassesAnnotatedWithEntityToBeScanned(){
        Reflections reflections = new Reflections(".*");
        Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(EntityToBeScanned.class);
        return annotated;
    }

}

ক্লাসগুলির একটি সেট পাওয়ার জন্য allFoundClassesAnnotatedWithEntityToBeScanned () পদ্ধতিটি কল করুন।

আপনি নীচের libs প্রয়োজন হবে

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>21.0</version>
    </dependency>
<!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.22.0-CR1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.reflections/reflections -->
<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.9.10</version>
</dependency>

উল্লেখ উল্লেখযোগ্য

আপনি যদি কিছু প্যাকেজের অধীনে সমস্ত ক্লাসগুলির একটি তালিকা পেতে চান তবে আপনি Reflectionনিম্নোক্ত উপায়ে ব্যবহার করতে পারেন :

List<Class> myTypes = new ArrayList<>();

Reflections reflections = new Reflections("com.package");
for (String s : reflections.getStore().get(SubTypesScanner.class).values()) {
    myTypes.add(Class.forName(s));
}

এটি ক্লাসগুলির একটি তালিকা তৈরি করবে যা আপনি পরে ইচ্ছা করলে তাদের ব্যবহার করতে পারবেন।


share@RunWith(Parameterized.class) যখন ম্যেন ব্যবহার করে তখন পরামিতি পরীক্ষার জন্য আমার জন্য কাজ করে নি । পরীক্ষার সঠিকভাবে নামকরণ করা হয় এবং যেখানে পাওয়া যায় কিন্তু মৃত্যুদন্ড কার্যকর করা হয় নি:

-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running some.properly.named.test.run.with.maven.SomeTest
Tests run: 0, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.123 sec

একটি অনুরূপ সমস্যা here রিপোর্ট করা here ।

আমার ক্ষেত্রে @Parametersএকটি প্যাকেজ প্রতিটি ক্লাসের দৃষ্টান্ত তৈরি হয়। IDE স্থানীয়ভাবে রান যখন পরীক্ষা ভাল কাজ। যাইহোক, যখন ম্যাগেন চালানো হয় তখন কোন ক্লাস নেই যেখানে অ্যালেক্সান্ডার ব্লোমস্কল এর সমাধান পাওয়া যায়।

অ্যালেক্সান্ডার ব্লোমস্কল এর উত্তরে ডেভিড প্যারসনের মন্তব্যের দ্বারা অনুপ্রাণিত এইটি আমি নিচের নিচের চিত্রগুলির সাথে কাজ করেছিলাম:

Reflections reflections = new Reflections(new ConfigurationBuilder()
            .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
            .addUrls(ClasspathHelper.forJavaClassPath()) 
            .filterInputsBy(new FilterBuilder()
            .include(FilterBuilder.prefix(basePackage))));

Set<Class<?>> subTypesOf = reflections.getSubTypesOf(Object.class);

আমি প্রতিফলন গ্রন্থাগার ব্যবহার করার চেষ্টা করছি, কিন্তু এটি ব্যবহার করে কিছু সমস্যা ছিল, এবং সেখানে অনেকগুলি জার্স ছিল যা কেবল প্যাকেজগুলিতে কেবল ক্লাসগুলি পাওয়ার জন্য অন্তর্ভুক্ত করা উচিত।

আমি এই সদৃশ প্রশ্নে পাওয়া একটি সমাধান পোস্ট করব: প্যাকেজগুলিতে সমস্ত ক্লাসের নাম কীভাবে পেতে হয়?

উত্তর sp00m দ্বারা লিখিত হয় ; আমি এটি কাজ করতে কিছু সংশোধন যোগ করেছি:

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.List;

public final class ClassFinder {

    private final static char DOT = '.';
    private final static char SLASH = '/';
    private final static String CLASS_SUFFIX = ".class";
    private final static String BAD_PACKAGE_ERROR = "Unable to get resources from path '%s'. Are you sure the given '%s' package exists?";

    public final static List<Class<?>> find(final String scannedPackage) {
        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        final String scannedPath = scannedPackage.replace(DOT, SLASH);
        final Enumeration<URL> resources;
        try {
            resources = classLoader.getResources(scannedPath);
        } catch (IOException e) {
            throw new IllegalArgumentException(String.format(BAD_PACKAGE_ERROR, scannedPath, scannedPackage), e);
        }
        final List<Class<?>> classes = new LinkedList<Class<?>>();
        while (resources.hasMoreElements()) {
            final File file = new File(resources.nextElement().getFile());
            classes.addAll(find(file, scannedPackage));
        }
        return classes;
    }

    private final static List<Class<?>> find(final File file, final String scannedPackage) {
        final List<Class<?>> classes = new LinkedList<Class<?>>();
        if (file.isDirectory()) {
            for (File nestedFile : file.listFiles()) {
                classes.addAll(find(nestedFile, scannedPackage));
            }
        //File names with the $1, $2 holds the anonymous inner classes, we are not interested on them. 
        } else if (file.getName().endsWith(CLASS_SUFFIX) && !file.getName().contains("$")) {

            final int beginIndex = 0;
            final int endIndex = file.getName().length() - CLASS_SUFFIX.length();
            final String className = file.getName().substring(beginIndex, endIndex);
            try {
                final String resource = scannedPackage + DOT + className;
                classes.add(Class.forName(resource));
            } catch (ClassNotFoundException ignore) {
            }
        }
        return classes;
    }

}

এটি ব্যবহার করার জন্য শুধুমাত্র এই উদাহরণে বর্ণিত sp00n হিসাবে খোঁজার পদ্ধতিটি কল করুন: প্রয়োজন হলে আমি ক্লাসগুলির দৃষ্টান্ত তৈরি করেছি।

List<Class<?>> classes = ClassFinder.find("com.package");

ExcelReporting excelReporting;
for (Class<?> aClass : classes) {
    Constructor constructor = aClass.getConstructor();
    //Create an object of the class type
    constructor.newInstance();
    //...
}

আমি শুধু একটি ব্যবহার ক্লাস লিখেছি, এটি পরীক্ষা পদ্ধতি অন্তর্ভুক্ত, আপনি একটি চেক করতে পারেন ~

IteratePackageUtil.java:

package eric.j2se.reflect;

import java.util.Set;

import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

/**
 * an util to iterate class in a package,
 * 
 * @author eric
 * @date Dec 10, 2013 12:36:46 AM
 */
public class IteratePackageUtil {
    /**
     * <p>
     * Get set of all class in a specified package recursively. this only support lib
     * </p>
     * <p>
     * class of sub package will be included, inner class will be included,
     * </p>
     * <p>
     * could load class that use the same classloader of current class, can't load system packages,
     * </p>
     * 
     * @param pkg
     *            path of a package
     * @return
     */
    public static Set<Class<? extends Object>> getClazzSet(String pkg) {
        // prepare reflection, include direct subclass of Object.class
        Reflections reflections = new Reflections(new ConfigurationBuilder().setScanners(new SubTypesScanner(false), new ResourcesScanner())
                .setUrls(ClasspathHelper.forClassLoader(ClasspathHelper.classLoaders(new ClassLoader[0])))
                .filterInputsBy(new FilterBuilder().includePackage(pkg)));

        return reflections.getSubTypesOf(Object.class);
    }

    public static void test() {
        String pkg = "org.apache.tomcat.util";

        Set<Class<? extends Object>> clazzSet = getClazzSet(pkg);
        for (Class<? extends Object> clazz : clazzSet) {
            System.out.println(clazz.getName());
        }
    }

    public static void main(String[] args) {
        test();
    }
}

ক্লাস ক্লাসে প্রতিটি ক্লাস লোডার এন্ট্রি সন্ধান করতে হবে:

    String pkg = "org/apache/commons/lang";
    ClassLoader cl = ClassLoader.getSystemClassLoader();
    URL[] urls = ((URLClassLoader) cl).getURLs();
    for (URL url : urls) {
        System.out.println(url.getFile());
        File jar = new File(url.getFile());
        // ....
    }   

এন্ট্রি ডিরেক্টরি হলে, ডানদিকের সাবডিরেক্টরিতে সন্ধান করুন:

if (jar.isDirectory()) {
    File subdir = new File(jar, pkg);
    if (!subdir.exists())
        continue;
    File[] files = subdir.listFiles();
    for (File file : files) {
        if (!file.isFile())
            continue;
        if (file.getName().endsWith(".class"))
            System.out.println("Found class: "
                    + file.getName().substring(0,
                            file.getName().length() - 6));
    }
}   

যদি এন্ট্রিটি ফাইল হয় এবং এটি জার থাকে তবে এর জীপ এন্ট্রিগুলি পরিদর্শন করুন:

else {
    // try to open as ZIP
    try {
        ZipFile zip = new ZipFile(jar);
        for (Enumeration<? extends ZipEntry> entries = zip
                .entries(); entries.hasMoreElements();) {
            ZipEntry entry = entries.nextElement();
            String name = entry.getName();
            if (!name.startsWith(pkg))
                continue;
            name = name.substring(pkg.length() + 1);
            if (name.indexOf('/') < 0 && name.endsWith(".class"))
                System.out.println("Found class: "
                        + name.substring(0, name.length() - 6));
        }
    } catch (ZipException e) {
        System.out.println("Not a ZIP: " + e.getMessage());
    } catch (IOException e) {
        System.err.println(e.getMessage());
    }
}

এখন আপনার প্যাকেজের সাথে সমস্ত ক্লাস নাম থাকা একবার, আপনি প্রতিফলন সহ লোড করার চেষ্টা করতে পারেন এবং শ্রেণী বা ইন্টারফেসগুলি কিনা তা বিশ্লেষণ করতে পারেন।


তবে আপনি কোনও গতিশীল ক্লাস লোডার ব্যবহার করছেন না যা আপনি ক্লাসপথ অনুসন্ধান করতে পারেন এবং প্রতিটি এন্ট্রিটির জন্য ডিরেক্টরি বা জার ফাইলটি অনুসন্ধান করুন।


এটি খুব সম্ভব, তবে Reflectionsএটির মতো অতিরিক্ত লাইব্রেরিগুলি কঠিন নয় ...
এটি কঠিন কারণ আপনার ক্লাসের নাম পেতে সম্পূর্ণ যন্ত্র নেই।
এবং, আমি আমার ClassFinderক্লাসের কোডটি গ্রহণ করি :

package play.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Created by LINKOR on 26.05.2017 in 15:12.
 * Date: 2017.05.26
 */
public class FileClassFinder {
private JarFile file;
private boolean trouble;
public FileClassFinder(String filePath) {
    try {
        file = new JarFile(filePath);
    } catch (IOException e) {
        trouble = true;
    }
}

public List<String> findClasses(String pkg) {
    ArrayList<String> classes = new ArrayList<>();
    Enumeration<JarEntry> entries = file.entries();
    while (entries.hasMoreElements()) {
        JarEntry cls = entries.nextElement();
        if (!cls.isDirectory()) {
            String fileName = cls.getName();
            String className = fileName.replaceAll("/",         ".").replaceAll(File.pathSeparator, ".").substring(0, fileName.lastIndexOf('.'));
            if (className.startsWith(pkg)) classes.add(className.substring(pkg.length() + 1));
        }
    }
    return classes;
}
}

প্রায় সব উত্তর Reflectionsফাইল সিস্টেম থেকে ক্লাস ফাইল ব্যবহার করে বা পড়তে পারে। যদি আপনি ফাইল সিস্টেম থেকে ক্লাস পড়ার চেষ্টা করেন, আপনি যখন JAR বা অন্য হিসাবে আপনার অ্যাপ্লিকেশন প্যাকেজ করবেন তখন ত্রুটিগুলি পেতে পারে। এছাড়াও আপনি যে উদ্দেশ্যে একটি পৃথক লাইব্রেরি ব্যবহার করতে চান না।

এখানে অন্য পদ্ধতি যা বিশুদ্ধ জাভা এবং ফাইল সিস্টেমের উপর নির্ভর করে না।

import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

public class PackageUtil {

    public static Collection<Class> getClasses(final String pack) throws Exception {
        final StandardJavaFileManager fileManager = ToolProvider.getSystemJavaCompiler().getStandardFileManager(null, null, null);
        return StreamSupport.stream(fileManager.list(StandardLocation.CLASS_PATH, pack, Collections.singleton(JavaFileObject.Kind.CLASS), false).spliterator(), false)
                .map(javaFileObject -> {
                    try {
                        final String[] split = javaFileObject.getName()
                                .replace(".class", "")
                                .replace(")", "")
                                .split(Pattern.quote(File.separator));

                        final String fullClassName = pack + "." + split[split.length - 1];
                        return Class.forName(fullClassName);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }

                })
                .collect(Collectors.toCollection(ArrayList::new));
    }
}

জাভা 8 একটি আবশ্যক নয় । আপনি স্ট্রিম পরিবর্তে loops জন্য ব্যবহার করতে পারেন। এবং আপনি এটি ভালো পরীক্ষা করতে পারেন

public static void main(String[] args) throws Exception {
    final String pack = "java.nio.file"; // Or any other package
    PackageUtil.getClasses(pack).stream().forEach(System.out::println);
}






packages