Class ClassQuery<C>

  • Type Parameters:
    C - Base type for returned classes.
    All Implemented Interfaces:
    Iterable<Class<? extends C>>

    public final class ClassQuery<C>
    extends Object
    Iterable-like container that searches for classes.

    This is straightforward method to search for classes that have specified characteristics when one doesn't have their name.

    Instances of this class are immutable, each filtering produces new, modified instance. To obtain unrestricted query, use system() or of(ClassLoader).

    To obtain results either iterate this class with Iterable.iterator() (or in enhanced-for loop) or use one of stream(), unique(), option() or isPresent().

    This query works in three stages, from fastest to slowest. First it reads classpath entries looking for class files. At this point it filters for package and class names. These are the fastest filters that can immeasurably speed up querying, and it is suggested that all queries should have at least one of these filters.

    Then, it uses Javassist classfile reading, which only parses the classfile, without initializing it. At this point, the query can filter for things like checking if annotation is present or if interface is implemented. These filters are much faster that conventional classloading (because class dependencies don't have to be loaded and no class initialization actually occurs).

    Lastly, class is loaded and arbitrary filtering on it is applied.

    If unrestricted, this query is very slow, as it will load all classes either in classloader or on classpath!

    Example usage, which registers all classes in package "org.perfectable" that implements Serializable and are annotated by javax.annotation.Generated:

         ClassQuery.of(Application.class.getClassloader())
             .inPackage("org.perfectable")
             .subtypeOf(java.io.Serializable.class)
             .annotatedBy(javax.annotation.Generated.class)
             .stream()
             .forEach(this::register);
     
    • Method Detail

      • system

        public static ClassQuery<Object> system()
        Queries for all classes reachable from declared classpath.
        Returns:
        query for system classloader classes.
      • of

        public static ClassQuery<Object> of​(ClassLoader loader)
        Queries for classes reachable by specified classloader.
        Parameters:
        loader - classloader to introspect
        Returns:
        query for classes in classloader
      • subtypeOf

        public <X extends CClassQuery<X> subtypeOf​(Class<? extends X> supertype)
        Restricts query to classes that are subtype of specified type.

        This restriction works on unloaded classes and gives some speedup when obtaining results of query.

        Type Parameters:
        X - new supertype bound
        Parameters:
        supertype - class which will be supertype of any result returned by this query
        Returns:
        query for classes with specific supertype
      • inPackage

        public ClassQuery<C> inPackage​(String filteredPackageName)
        Restricts query to classes that in specified package or its descendants.

        This restriction works on class names and gives generous speedup when obtaining results of query.

        Parameters:
        filteredPackageName - name of the package which will restrict results
        Returns:
        query that returns classes in specified package
      • inPackage

        public ClassQuery<C> inPackage​(Package filteredPackage)
        Restricts query to classes that in specified package or its descendants.

        This restriction works on class names and gives generous speedup when obtaining results of query.

        Parameters:
        filteredPackage - package which will restrict results
        Returns:
        query that returns classes in specified package
      • filter

        public ClassQuery<C> filter​(Predicate<? super Class<? extends C>> filter)
        Restricts query to classes that matches specified predicate.

        This restriction works on loaded classes and gives no speedup when obtaining results of query.

        Parameters:
        filter - predicate that will determine if this query will contain element
        Returns:
        query returning the same elements as this one, but only if they match the predicate
      • annotatedWith

        public ClassQuery<C> annotatedWith​(Class<? extends Annotation> annotation)
        Restricts query to classes that are annotated by annotation with specified class.

        This restriction works on unloaded classes and gives some speedup when obtaining results of query.

        Parameters:
        annotation - annotation that must be present on class to be returned
        Returns:
        query that returns only classes that have specific annotation
      • annotatedWith

        public ClassQuery<C> annotatedWith​(AnnotationFilter annotationFilter)
        Restricts query to classes that matches specified annotation filter.

        This restriction works on unloaded classes and gives some speedup when obtaining results of query.

        Parameters:
        annotationFilter - filter for annotation on class
        Returns:
        query that returns classes matching specified filter
      • stream

        public Stream<Class<? extends C>> stream()
        Adapts this query to a Stream.
        Returns:
        stream with elements of this query
      • contains

        public boolean contains​(Object candidate)
        Checks if provided object is in elements that would be returned by this query.

        This is often faster than checking by iteration, and most queries in library override this method, but this is not guaranteed, as it might not be possible.

        Parameters:
        candidate - object to check if it is contained in this query.
        Returns:
        if object would be returned by the query
      • unique

        public final E unique()
        Returns single element that this query contains.
        Returns:
        single element matches by this query
        Throws:
        NoSuchElementException - if this query didn't contain any element
        IllegalArgumentException - if the query contains multiple elements
      • isPresent

        public boolean isPresent()
        Checks if any element was contained in query.
        Returns:
        true if at least one element is present in this query
      • option

        public final Optional<E> option()
        Fetches only element present in this query, or empty optional.
        Returns:
        single element matched by this query, or empty optional.
        Throws:
        IllegalArgumentException - if the query contains multiple elements