ReflectionUtil { @SuppressWarnings("unchecked") public static <T> String errorMsg(Class<T> c, List<Object> instances) { final Predicate<Constructor<?>> onlyInject; if (hasConstructorWithInjectAnnotation(c)) { onlyInject = constr -> constr.isAnnotationPresent(Inject.class); } else { onlyInject = constr -> true; } return String.format("%s: %n", c.getSimpleName()) + Arrays.stream(c.getDeclaredConstructors()) .map(constructor -> (Constructor<T>) constructor) .filter(onlyInject) .map(con -> String.format(" %s %s %n %s ", con.isAnnotationPresent(Inject.class) ? "@Inject" : " ", con.toString(), Stream.of(con.getParameters()) .map(p -> { if (paramIsConfig(p)) { return String.format(" %s %s%n", Config.class.getSimpleName(), p.toString()); } else { return String.format(" %s %s%n", p.toString(), paramIsInjectable(p, instances) ? "" : " <-- Missing"); } }).collect(joining(String.format("%n"))) ) ).collect(joining(String.format("%n"))); } private  ReflectionUtil(); static Stream<Field> traverseFields(Class<?> clazz); static Stream<Method> traverseMethods(Class<?> clazz); static Stream<Class<?>> traverseAncestors(Class<?> clazz); static MissingArgumentStrategy missingArgumentStrategy(Executable executable); static Optional<T> tryToCreate(Class<T> clazz, Properties properties, List<Object> instances, Set<Class<?>> allInjectableTypes, InjectorProxy injectorProxy); @SuppressWarnings("unchecked") static String errorMsg(Class<T> c, List<Object> instances); static Optional<Object> parse(Type type, String serialized);  }
@Test void errorMsg() { final String actual = ReflectionUtil.errorMsg(Baz.class, Arrays.asList(String.class, Long.class)); assertTrue(actual.contains(Baz.class.getName())); assertTrue(actual.contains(Foo.class.getSimpleName())); assertTrue(actual.contains("Missing")); }