class Reflections {

    public <T> Set<Class<? extends T>> getSubTypesOf(Class<T> clazz) {
        ensureScan();
        synchronized (MONITOR) {
            @SuppressWarnings("rawtypes") // necessary for generic conversion. but safe here
            Set x = classToSubTypes.get(clazz);
            @SuppressWarnings("unchecked")
            Set<Class<? extends T>> result = x;
            if (result != null) {
                return result;
            }
            /* not tried before... */
            Set<Class<? extends T>> newresult = new LinkedHashSet<>();
            visitEveryClass(new Visitor() {

                @SuppressWarnings("unchecked")
                @Override
                public void visit(Class<?> clazzToInspect) {
                    if (clazzToInspect==clazz) {
                        return;
                    }
                    if (clazz.isAssignableFrom(clazzToInspect)) {
                        newresult.add((Class<? extends T>) clazzToInspect);
                    }

                }
            });
            classToSubTypes.put(clazz, newresult);
            return newresult;
        }
    }

    public  Reflections();

}