You really need to use both the class being built, and the builder, as parameters on the builder. The object being build does not need to know about the builder, however, so does not require it as a parameter.

I have used this pattern or slight variations in several open source projects, including Apache Brooklyn and jclouds.

Note that I added an abstract build() method as well, which will return the built object. The self() method is required because when if builder methods were to return this it would have the wrong type. Instead, each builder method must end with return self(); as in the example(String value) method shown. Then the child becomes:

You can see that the T and B generic parameters are being used to point to the type of the class and the type of the builder respectively. So, to make a concrete class that uses these, something like this should be created:

This also has a static builder() method, that returns an instance of the correct Builder class, you could also call the constructor directly if you want as well. The build() method simply creates and returns the concrete class, and the self() method is implemented here to return this which will have the correct type.

Putting everything together, we can use this to create a Hub object as follows:

Hub hub = Hub.Builder.builder()
.example("something")
.build();

Note that the AbstractDevice.Builder#example(String) method returns the correct type since it actually calls Hub#self(), and build() returns a concrete instance of Hub as expected.

To take a little of the pain out of this and remove the repeated boilerplate, you could also try using the Google AutoValue project, which we are switching to in jclouds now.