14

I am pretty much aware about builder pattern. Also already gone through with the builder pattern described in Item#2 in effective java of Joshua Bloch.

Here my question is - Is there any specific benefits to keep builder class inside the class which instantiates ?

We can also make it separate builder class and do the same thing.

Please be specific with your answers. AS I already know that inner class can access private members of building class and all this.

Bhavesh Dangi
  • 999
  • 1
  • 8
  • 14
  • 3
    http://programmers.stackexchange.com/a/225210 – Pramod Karandikar Jul 23 '15 at 06:06
  • 2
    Then you already know the answer. If it were in a separate class, the builder fields would have to be package-private or protected to be accessible by the final class constructor. And the final class constructor would also have to be package-private or protected to be accessible by the builder. Plus it would be a bit harder to find the Builder class when discovering the API. No big deals, but why not use a static inner class? – JB Nizet Jul 23 '15 at 06:08

3 Answers3

18

You obviously already know that a nested class (whether static or not) can access private members of the surrounding class.

So the real question is:

What member is it worth to be private and to access it from a builder?

And the answer is ... the constructor! You want to make the constructor private to not allow access at all. You want to allow access to the builder instead, but the builder must call the constructor at some time to ... well ... to build it.

If you have a builder that is not nested - maybe a top level class by itself - you must make the constructor of your target class at least package private. And this is usually not wanted.

Conclusion: The builder should be a nested class.

Oh, and the answer of Davide Lorenzo MARINO is also true: Of course it is also the strong relation of the builder and its surrounding class.

matrixanomaly
  • 6,627
  • 2
  • 35
  • 58
Seelenvirtuose
  • 20,273
  • 6
  • 37
  • 66
  • *Static nested classes do not have access to other members of the enclosing class.* [Refer to the official docs](https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html) – Raman Sahasi Oct 29 '17 at 17:11
  • @RamanSahasi And? Did you try? If you do, you will see, that you can access private instance members (via an object reference) and you can also access private class members - from that nested static class. – Seelenvirtuose Oct 29 '17 at 17:20
14

First: It is defined as inner class because it is strongly related to the outer class. From oracle site:

It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.

Second: It is defined as static because if the inner class is not static you can't instatiate it without creating an instance of the outer class.

As an additional nice behaviour you can define the constructor of the outer class private. So it is not possible to create the outer class without an explicit call to the builder.

And more as stated by JB Nizet in the comments of the question it is easier to find the builder in the javadoc searching for the outer class.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
  • Thanks Davide Lorenzo MARINO! We can relate them with naming conventions. Lets say if my class name is 'String' then I can have separate 'StringBuilder' class. – Bhavesh Dangi Jul 23 '15 at 06:10
  • I edit my answer to show you additional useful behaviour of the static inner class. – Davide Lorenzo MARINO Jul 23 '15 at 06:11
  • @Bhavesh note that String and StringBuilder are not a class and an inner static class. And StringBuilder is not a real builder (as builder pattern). – Davide Lorenzo MARINO Jul 23 '15 at 06:16
  • Again private constructor of outer class will not work in case of inheritance. If I have two classes with is-a relationship and they have their inner builder classes. Also I know very well about String and StringBuilder. Just gave you an examples – Bhavesh Dangi Jul 23 '15 at 06:22
2

I think there are two reason for this.

  1. the builder can access to the outer cass private stuff so there is no need for setter that are accessible by others. -- I know that you already know.
  2. the builder class name will be the-package.Something.Builder which is self explanatory and do not cluster the package with so many classes.

Just my two cents.

NawaMan
  • 25,129
  • 10
  • 51
  • 77