reflect

Gentle reflection of types, names and resources

Consists of static methods across four classes:

  1. Methods
    • All methods of a given class (inherited, overridden)
    • Easily acquire a MethodHandle (works in Java 8, 9 and 10)
  2. Names
    • Class names to/from binary, descriptor and resource
  3. Resources
    • Get the bytecode for a class
    • Find a class’ location
  4. Types
    • Overloaded to accept java.lang.Class, java.lang.reflect.Type and java.lang.String
    • isA methods for primitive, primitive-wrapper, interface and class
    • Find all interfaces/supertypes
    • Query implements/extends
    • Convert primitives to/from wrappers
    • requiresInterface/requiresClass argument checkers

Dependency Graph

Module Dependency

Examples

Method handle

Find a method and then get a handle for it:

public String taDa()
{
	return "TA-DA";
}

@Test
public void handleForNormalMethod() throws Throwable
{
	Method method = Methods.getMethod(MethodsTest.class, "taDa")
			.orElseThrow(NullPointerException::new);

	MethodHandle handle = Methods.handleFor(method).bindTo(this);

	assertThat(handle.invoke(), is(equalTo(taDa())));
}

(source)

Find resource

For a given class, locate it’s origin, in a directory:

	String resource = Resources.sourceOfResource(ResourcesTest.class);

	assertThat(resource, new File(resource), is(anExistingDirectory()));

	assertThat(resource, endsWith("/target/test-classes/"));

Or in a JAR:

	String resource = Resources.sourceOfResource(Immutable.class);

	assertThat(new File(resource), is(aReadableFile()));

	assertThat(resource, allOf(
			containsString("/com/google/code/findbugs/jsr305/"),
			endsWith(".jar")));

(source)

Names

Get a binary name for a type:

	String typeToDescriptor = Names.typeToDescriptor(Map.Entry.class).toString();

	assertThat(typeToDescriptor, is(equalTo("Ljava/util/Map$Entry;")));

Get a binary name for a type:

	String binaryName = Names.internalToTypeName("[[Ljava/lang/Object;");

	assertThat(binaryName, is(equalTo(Object[][].class.getTypeName())));

List all binary names declared within a compilation unit:

Given:

private class Declares {
	private class DeclaredTop {
		private class DeclaredMiddle {
			private class DeclaredBottom {}

			private final Comparator<String> anon = new Comparator<String>() {
				@Override
				public int compare(String o1, String o2)
				{
					return 0;
				}
			};

			public String x()
			{
				Supplier<String> supplier = new Supplier<String>() {

					@Override
					public String get()
					{
						return "hello";
					}

				};
				return supplier.get();
			}
		}
	}
}

We shall use:

	List<String> classes = Names.declaredInternalNamesOf(Declares.class).collect(toList());

	assertThat(classes, containsInAnyOrder(
			typeToInternalName(Declares.DeclaredTop.class),
			typeToInternalName(Declares.DeclaredTop.DeclaredMiddle.class),
			typeToInternalName(Declares.DeclaredTop.DeclaredMiddle.class) + "$1",
			typeToInternalName(Declares.DeclaredTop.DeclaredMiddle.class) + "$2",
			typeToInternalName(Declares.DeclaredTop.DeclaredMiddle.DeclaredBottom.class)));

(source)

Types

Argument checking requires* methods, such as:

	try {
		requireClass(Comparable.class);
		fail();
	} catch(IllegalArgumentException e) {}

Query methods, such as:

	assertThat(Types.implementsAll(String.class,
			Serializable.class,
			Comparable.class,
			CharSequence.class), is(true));

(source)

Back to top

Version: 0.1.0. Last Published: 2018-10-08.

Earcam Maven Skin.