¿Puedes encontrar todas las clases en un paquete utilizando la reflexión?

¿Es posible encontrar todas las clases o interfaces en un paquete dado? (Mirando rápidamente, por ejemplo, el Package , parece que no).

Debido a la naturaleza dinámica de los cargadores de clase, esto no es posible. No es necesario que los cargadores de clases le digan a la VM qué clases puede proporcionar, sino que simplemente se les entregan las solicitudes de clases y tienen que devolver una clase o lanzar una excepción.

Sin embargo, si escribe sus propios cargadores de clase o examina los classpaths y sus jarras, es posible encontrar esta información. Sin embargo, esto será a través de las operaciones del sistema de archivos, y no de la reflexión. Incluso puede haber bibliotecas que puedan ayudarlo a hacer esto.

Si hay clases que se generan o entregan de forma remota, no podrá descubrir esas clases.

El método normal es en lugar de registrar en alguna parte las clases a las que necesita acceder en un archivo, o hacer referencia a ellas en una clase diferente. O simplemente usa la convención cuando se trata de nombrar.

Adición: La Biblioteca de Reflejos le permitirá buscar clases en la ruta de clase actual. Se puede usar para obtener todas las clases en un paquete:

  Reflections reflections = new Reflections("my.project.prefix"); Set> allClasses = reflections.getSubTypesOf(Object.class); 

Probablemente deberías echarle un vistazo a la biblioteca Reflections de código abierto. Con él puedes lograr fácilmente lo que quieres.

Primero, configure el índice de reflections (es un poco desordenado ya que la búsqueda de todas las clases está deshabilitada de forma predeterminada):

 List classLoadersList = new LinkedList(); classLoadersList.add(ClasspathHelper.contextClassLoader()); classLoadersList.add(ClasspathHelper.staticClassLoader()); Reflections reflections = new Reflections(new ConfigurationBuilder() .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner()) .setUrls(ClasspathHelper.forClassLoader(classLoadersList.toArray(new ClassLoader[0]))) .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix("org.your.package")))); 

Luego puede consultar todos los objetos en un paquete dado:

 Set> classes = reflections.getSubTypesOf(Object.class); 

Google Guava 14 incluye una nueva clase ClassPath con tres métodos para buscar clases de nivel superior:

  • getTopLevelClasses()
  • getTopLevelClasses(String packageName)
  • getTopLevelClassesRecursive(String packageName)

Vea los javadocs de ClassPath para más información.

Podría usar este método 1 que usa el ClassLoader .

  /** * 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 resources = classLoader.getResources(path); List dirs = new ArrayList(); while (resources.hasMoreElements()) { URL resource = resources.nextElement(); dirs.add(new File(resource.getFile())); } ArrayList classes = new ArrayList(); 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 findClasses(File directory, String packageName) throws ClassNotFoundException { List classes = new ArrayList(); 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 Este método se tomó originalmente de http://snippets.dzone.com/posts/show/4831 , que fue archivado por el Archivo de Internet, como está vinculado a ahora. El fragmento también está disponible en https://dzone.com/articles/get-all-classes-within-package .

Primavera

Este ejemplo es para Spring 4, pero también puede encontrar el escáner classpath en versiones anteriores.

 // 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 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 ... } 

Google Guava

Nota: En la versión 14, la API todavía está marcada como @Beta , así que ten cuidado con el código de producción.

 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 } } 

Hola. Siempre he tenido algunos problemas con las soluciones anteriores (y en otros sitios).
Yo, como desarrollador, estoy progtwigndo un complemento para una API. La API permite el uso de bibliotecas externas o herramientas de terceros. La configuración también consiste en una mezcla de código en archivos jar o zip y archivos de clase ubicados directamente en algunos directorios. Así que mi código tenía que ser capaz de funcionar alrededor de cada configuración. Después de una gran cantidad de investigaciones, he encontrado un método que funcionará en al menos el 95% de todas las configuraciones posibles.

El siguiente código es básicamente el método de overkill que siempre funcionará.

El código:

Este código escanea un paquete dado para todas las clases que están incluidas en él. Solo funcionará para todas las clases en el ClassLoader actual.

 /** * Private helper method * * @param directory * The directory to start with * @param pckgname * The package name to search for. Will be needed for getting the * Class object. * @param classes * if a file isn't loaded but still is in the directory * @throws ClassNotFoundException */ private static void checkDirectory(File directory, String pckgname, ArrayList> classes) throws ClassNotFoundException { File tmpDirectory; if (directory.exists() && directory.isDirectory()) { final String[] files = directory.list(); for (final String file : files) { if (file.endsWith(".class")) { try { classes.add(Class.forName(pckgname + '.' + file.substring(0, file.length() - 6))); } catch (final NoClassDefFoundError e) { // do nothing. this class hasn't been found by the // loader, and we don't care. } } else if ((tmpDirectory = new File(directory, file)) .isDirectory()) { checkDirectory(tmpDirectory, pckgname + "." + file, classes); } } } } /** * Private helper method. * * @param connection * the connection to the jar * @param pckgname * the package name to search for * @param classes * the current ArrayList of all classes. This method will simply * add new classes. * @throws ClassNotFoundException * if a file isn't loaded but still is in the jar file * @throws IOException * if it can't correctly read from the jar file. */ private static void checkJarFile(JarURLConnection connection, String pckgname, ArrayList> classes) throws ClassNotFoundException, IOException { final JarFile jarFile = connection.getJarFile(); final Enumeration entries = jarFile.entries(); String name; for (JarEntry jarEntry = null; entries.hasMoreElements() && ((jarEntry = entries.nextElement()) != null);) { name = jarEntry.getName(); if (name.contains(".class")) { name = name.substring(0, name.length() - 6).replace('/', '.'); if (name.contains(pckgname)) { classes.add(Class.forName(name)); } } } } /** * Attempts to list all the classes in the specified package as determined * by the context class loader * * @param pckgname * the package name to search * @return a list of classes that exist within that package * @throws ClassNotFoundException * if something went wrong */ public static ArrayList> getClassesForPackage(String pckgname) throws ClassNotFoundException { final ArrayList> classes = new ArrayList>(); try { final ClassLoader cld = Thread.currentThread() .getContextClassLoader(); if (cld == null) throw new ClassNotFoundException("Can't get class loader."); final Enumeration resources = cld.getResources(pckgname .replace('.', '/')); URLConnection connection; for (URL url = null; resources.hasMoreElements() && ((url = resources.nextElement()) != null);) { try { connection = url.openConnection(); if (connection instanceof JarURLConnection) { checkJarFile((JarURLConnection) connection, pckgname, classes); } else if (connection instanceof FileURLConnection) { try { checkDirectory( new File(URLDecoder.decode(url.getPath(), "UTF-8")), pckgname, classes); } catch (final UnsupportedEncodingException ex) { throw new ClassNotFoundException( pckgname + " does not appear to be a valid package (Unsupported encoding)", ex); } } else throw new ClassNotFoundException(pckgname + " (" + url.getPath() + ") does not appear to be a valid package"); } catch (final IOException ioex) { throw new ClassNotFoundException( "IOException was thrown when trying to get all resources for " + pckgname, ioex); } } } catch (final NullPointerException ex) { throw new ClassNotFoundException( pckgname + " does not appear to be a valid package (Null pointer exception)", ex); } catch (final IOException ioex) { throw new ClassNotFoundException( "IOException was thrown when trying to get all resources for " + pckgname, ioex); } return classes; } 

Estos tres métodos le proporcionan la capacidad de encontrar todas las clases en un paquete determinado.
Lo usas así:

 getClassesForPackage("package.your.classes.are.in"); 

La explicación:

El método primero obtiene el ClassLoader actual. A continuación, obtiene todos los recursos que contienen dicho paquete e itera de estos URL s. Luego crea una URLConnection y determina qué tipo de URL tenemos. Puede ser un directorio ( FileURLConnection ) o un directorio dentro de un archivo jar o zip ( JarURLConnection ). Según el tipo de conexión, se llamarán dos métodos diferentes.

Primero veamos qué pasa si es un FileURLConnection .
Primero verifica si el archivo pasado existe y es un directorio. Si ese es el caso, verifica si se trata de un archivo de clase. Si es así, se creará un objeto Class y se colocará en ArrayList . Si no es un archivo de clase sino un directorio, simplemente iteramos en él y hacemos lo mismo. Todos los demás casos / archivos serán ignorados.

Si el URLConnection es un URLConnection se JarURLConnection al otro método de ayuda privada. Este método itera sobre todas las entradas en el archivo zip / jar. Si una entrada es un archivo de clase y está dentro del paquete, se creará y almacenará un objeto Class en ArrayList .

Después de que todos los recursos se hayan analizado (el método principal) devuelve ArrayList contiene todas las clases en el paquete dado, que el ClassLoader actual conoce.

Si el proceso falla en algún punto, se lanzará una ClassNotFoundException que contiene información detallada sobre la causa exacta.

Sin usar ninguna biblioteca adicional:

 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 classes = getClasses(Test.class.getClassLoader(),"test"); for(Class c:classes){ System.out.println("Class: "+c); } } public static List getClasses(ClassLoader cl,String pack) throws Exception{ String dottedPackage = pack.replaceAll("[/]", "."); List classes = new ArrayList(); 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; } } 

En general, los cargadores de clases no permiten el escaneo a través de todas las clases en el classpath. Pero generalmente el único cargador de clases utilizado es UrlClassLoader desde el que podemos recuperar la lista de directorios y archivos jar (ver getURLs ) y abrirlos uno por uno para enumerar las clases disponibles. Este enfoque, llamado exploración de ruta de clases, se implementa en Scannotation y Reflections .

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

Otro enfoque es utilizar la API de procesamiento de anotación conectable de Java para escribir un procesador de anotación que recogerá todas las clases anotadas en tiempo de comstackción y creará el archivo de índice para su uso en tiempo de ejecución. Este mecanismo se implementa en la biblioteca ClassIndex :

 // package-info.java @IndexSubclasses package my.package; // your code Iterable classes = ClassIndex.getPackageClasses("my.package"); 

Tenga en cuenta que no es necesaria ninguna configuración adicional ya que el escaneo está totalmente automatizado gracias al comstackdor de Java que detecta automáticamente cualquier procesador que se encuentre en el classpath.

Escribí FastClasspathScanner para resolver este problema. Maneja muchos tipos diferentes de tareas de escaneo de classpath, tiene una API simple, funciona con muchos entornos diferentes ClassLoaders y classpath, ha sido cuidadosamente paralelizado y está altamente optimizado para alta velocidad y bajo consumo de memoria. Incluso puede generar una visualización GraphViz del gráfico de clase, que muestra cómo las clases están conectadas entre sí.

Para su pregunta original de encontrar todas las clases o interfaces en un paquete dado, puede hacer:

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

Hay muchas variantes posibles para esto: consulte la documentación (vinculada arriba) para obtener información completa.

Así es como lo hago. Escaneo todas las subcarpetas (subpaquetes) y no bash cargar clases anónimas:

  /** * Attempts to list all the classes in the specified package as determined * by the context class loader, recursively, avoiding anonymous classes * * @param pckgname * the package name to search * @return a list of classes that exist within that package * @throws ClassNotFoundException * if something went wrong */ private static List getClassesForPackage(String pckgname) throws ClassNotFoundException { // This will hold a list of directories matching the pckgname. There may be more than one if a package is split over multiple jars/paths ArrayList directories = new ArrayList(); String packageToPath = pckgname.replace('.', '/'); try { ClassLoader cld = Thread.currentThread().getContextClassLoader(); if (cld == null) { throw new ClassNotFoundException("Can't get class loader."); } // Ask for all resources for the packageToPath Enumeration resources = cld.getResources(packageToPath); while (resources.hasMoreElements()) { directories.add(new File(URLDecoder.decode(resources.nextElement().getPath(), "UTF-8"))); } } catch (NullPointerException x) { throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Null pointer exception)"); } catch (UnsupportedEncodingException encex) { throw new ClassNotFoundException(pckgname + " does not appear to be a valid package (Unsupported encoding)"); } catch (IOException ioex) { throw new ClassNotFoundException("IOException was thrown when trying to get all resources for " + pckgname); } ArrayList classes = new ArrayList(); // For every directoryFile identified capture all the .class files while (!directories.isEmpty()){ File directoryFile = directories.remove(0); if (directoryFile.exists()) { // Get the list of the files contained in the package File[] files = directoryFile.listFiles(); for (File file : files) { // we are only interested in .class files if ((file.getName().endsWith(".class")) && (!file.getName().contains("$"))) { // removes the .class extension int index = directoryFile.getPath().indexOf(packageToPath); String packagePrefix = directoryFile.getPath().substring(index).replace('/', '.');; try { String className = packagePrefix + '.' + file.getName().substring(0, file.getName().length() - 6); classes.add(Class.forName(className)); } catch (NoClassDefFoundError e) { // do nothing. this class hasn't been found by the loader, and we don't care. } } else if (file.isDirectory()){ // If we got to a subdirectory directories.add(new File(file.getPath())); } } } else { throw new ClassNotFoundException(pckgname + " (" + directoryFile.getPath() + ") does not appear to be a valid package"); } } return classes; } 

Arreglé un proyecto simple de Github que resuelve este problema:

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

Debería funcionar tanto para classpaths basados ​​en archivos como para archivos jar.

Si ejecuta ‘make’ después de verificar el proyecto, lo imprimirá:

  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. 

Ver también mi otra respuesta

Sí, usando pocas API puedes, aquí es cómo me gusta hacerlo, enfrenté este problema que estaba usando hibernate core y tuve que encontrar clases que estaban anotadas con una cierta anotación.

Realice una anotación personalizada con la que marcará las clases que desea que sean recogidas.

 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 { } 

Luego marca tu clase con ella como

 @EntityToBeScanned public MyClass{ } 

Haga esta clase de utilidad que tiene el siguiente método

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

Llame al método allFoundClassesAnnotatedWithEntityToBeScanned () para encontrar un conjunto de clases.

Necesitarás libs dados a continuación

   com.google.guava guava 21.0    org.javassist javassist 3.22.0-CR1    org.reflections reflections 0.9.10  

Necesita buscar cada entrada del cargador de clases en la ruta de la clase:

  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()); // .... } 

Si la entrada es un directorio, simplemente busque en el subdirectorio derecho:

 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)); } } 

Si la entrada es el archivo, y es jar, inspeccione las entradas ZIP de la misma:

 else { // try to open as ZIP try { ZipFile zip = new ZipFile(jar); for (Enumeration 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()); } } 

Ahora, una vez que tenga todos los nombres de clase dentro del paquete, puede intentar cargarlos con reflexión y analizar si son clases o interfaces, etc.

I’ve been trying to use the Reflections library, but had some problems using it, and there were too many jars I should include just to simply obtain the classes on a package.

I’ll post a solution I’ve found in this duplicate question: How to get all classes names in a package?

The answer was written by sp00m ; I’ve added some corrections to make it work:

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

To use it just call the find method as sp00n mentioned in this example: I’ve added the creation of instances of the classes if needed.

 List> classes = ClassFinder.find("com.package"); ExcelReporting excelReporting; for (Class aClass : classes) { Constructor constructor = aClass.getConstructor(); //Create an object of the class type constructor.newInstance(); //... } 

Almost all the answers either uses Reflections or reads class files from file system. If you try to read classes from file system, you may get errors when you package your application as JAR or other. Also you may not want to use a separate library for that purpose.

Here is another approach which is pure java and not depends on file system.

 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 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)); } } 

Java 8 is not a must . You can use for loops instead of streams. And you can test it like this

 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); } 

Worth mentioning

If you want to have a list of all classes under some package, you can use Reflection the following way:

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

This will create a list of classes that later you can use them as you wish.

Aleksander Blomskøld’s solution did not work for me for parameterized tests @RunWith(Parameterized.class) when using Maven. The tests were named correctly and also where found but not executed:

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

A similar issue has been reported here .

In my case @Parameters is creating instances of each class in a package. The tests worked well when run locally in the IDE. However, when running Maven no classes where found with Aleksander Blomskøld’s solution.

I did make it work with the following snipped which was inspired by David Pärsson’s comment on Aleksander Blomskøld’s answer:

 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> subTypesOf = reflections.getSubTypesOf(Object.class); 

Provided you are not using any dynamic class loaders you can search the classpath and for each entry search the directory or JAR file.

I just wrote a util class, it include test methods, you can have a check ~

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 { /** * 

* Get set of all class in a specified package recursively. this only support lib *

*

* class of sub package will be included, inner class will be included, *

*

* could load class that use the same classloader of current class, can't load system packages, *

* * @param pkg * path of a package * @return */ public static Set> 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> clazzSet = getClazzSet(pkg); for (Class clazz : clazzSet) { System.out.println(clazz.getName()); } } public static void main(String[] args) { test(); } }

It is very possible, but without additional libraries like Reflections it is hard…
It is hard because you haven’t full instrument for get class name.
And, I take the code of my ClassFinder class:

 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 findClasses(String pkg) { ArrayList classes = new ArrayList<>(); Enumeration 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; } } 

Based on @Staale’s answer , and in an attempt not to rely on third party libraries, I would implement the File System approach by inspecting first package physical location with:

 import java.io.File; import java.io.FileFilter; import java.util.ArrayList; ... Class[] foundClasses = new Class[0]; final ArrayList> foundClassesDyn = new ArrayList>(); new java.io.File( klass.getResource( "/" + curPackage.replace( "." , "/") ).getFile() ).listFiles( new java.io.FileFilter() { public boolean accept(java.io.File file) { final String classExtension = ".class"; if ( file.isFile() && file.getName().endsWith(classExtension) // avoid inner classes && ! file.getName().contains("$") ) { try { String className = file.getName(); className = className.substring(0, className.length() - classExtension.length()); foundClassesDyn.add( Class.forName( curPackage + "." + className ) ); } catch (ClassNotFoundException e) { e.printStackTrace(System.out); } } return false; } } ); foundClasses = foundClassesDyn.toArray(foundClasses); 

If you are merely looking to load a group of related classes, then Spring can help you.

Spring can instantiate a list or map of all classes that implement a given interface in one line of code. The list or map will contain instances of all the classes that implement that interface.

That being said, as an alternative to loading the list of classes out of the file system, instead just implement the same interface in all the classes you want to load, regardless of package and use Spring to provide you instances of all of them. That way, you can load (and instantiate) all the classes you desire regardless of what package they are in.

On the other hand, if having them all in a package is what you want, then simply have all the classes in that package implement a given interface.

It is not possible, since all classes in the package might not be loaded, while you always knows package of a class.