Sometimes the best way to learn new things is to explore. I have always been interested in the Java Reflection API so I decided to build something with it.

You know that programmers are lazy people. I’m not an exception. I especially hate to instantiate complex objects.

What would happen if I could inspect an object at run-time and build it without writing a single new?

Java Reflection API

Let’s begin with a simple example: we want to build nested classes. We have this class structure.

class A {

private final B b;

private final C c; public A(B b, C c) {

this.b = b;

this.c = c;

}

} class B {

public B() { }

} class C {

private final D d; public C(D d) {

this.d = d;

}

} class D {

public D() { }

}

To instantiate A we would need to write something like that:

A instance = new A(new B(), new C(new D()));

Pretty boring! What if instead, we could write:

A instance = NaiveBuilder.build(A.class);

The concept here is to delegate the control of creating objects to an algorithm instead of doing it by hand.

A naive algorithm

We could inspect the constructor and use recursion to resolve dependencies.

The following picture is a flowchart that describes the process.

For example, we start with our A and we find the first constructor. Since A depends on B and C we use recursion to call our algorithm on each dependency.

B has a constructor with no dependency so we instantiate it and return the call.

C has a constructor with a dependency, D, so we use recursion to call our algorithm on D.

D has a constructor with no dependency so we instantiate it and return the call.

Since we have D we can instantiate C.

Since we have B and D we can instantiate A.

Finally, the algorithm builds A to its dependencies.

Some observations

You may wonder why “we find the first constructor”. Java allows you to define many constructors on a class.

With the getConstructors method, you get a list of constructors that matches the order of definition.

Since our algorithm is simple, we arbitrarily select the first declared constructor.

We will explore how to select a specific constructor in another blog post .

This algorithm only resolves concrete classes. By this, I mean that Interfaces and other entities are not supported.

Again I choose this for simplicity and we will explore this aspect in-depth on another blog post.

The Circular dependency is not addressed. For the same reasons listed above.

Implementation

Given the above flowchart, the implementation is quite straightforward. We begin defining a build method:

public static <T> T build(Class<T> aClass) throws IllegalAccessException, InvocationTargetException, InstantiationException { Constructor<?> firstConstructor = aClass.getConstructors()[0];

if (hasDependencies(firstConstructor)) {

Object[] dependencies = resolve(firstConstructor);

return newInstance(firstConstructor, dependencies);

} return newInstance(firstConstructor);

}

Pay attention to the signature of the method. We capture the type of the class that we are going to build at compile time. This means:

A instance = NaiveBuilder.build(A.class); // valid A instance = NaiveBuilder.build(B.class); // invalid at compile time!

Conclusions

By any means this article is not going to reinvent the well. The problem discussed here is well defined and solved. You can find a plethora of libraries ready to be used but even the Java itself has a specification for that.

If you are familiar with Dependency Injection please note that this blog post is vague on purpose.

If you want to play around with this here it is the full Gist code.

Our journey with the Java reflection has just began!