But in most java codebases you can find the following implementation:
I hope I will not bust a big myth to you, but the 2 examples are identicle. The only difference is that the latter looks better.
So what's the fuss anyway? I'll tell you in a second. Imagine that you are a consumer of a Book instance and you have to read the title, author and the price of a book.
Since you can never be sure that the title of the book is set, you need to add a null check to every place where you try to read from the object. You can argue that the programmer should be disciplined enough to set the fields at every stage, but we are all just humans who make mistakes. But why would we deliberately make our lives error prone?
Mutable objectWith our current Book implementation, we created a mutable object. Why is that? Because you can alter the state of the book instance at any point of it's lifetime. It is born, it lives across your system then it dies. But while it lives, you can call the setters and change the title, the author and the price. Although the price might change over time, the title and author are unlikely to.
Why is this bad?As a programmer, you have to remember to set up the object correctly. You have to validate the data before you use it at every point. Unless you perfectly know the whole of your system, you'll never know what your Book consumer method will receive. Altering the state runtime may cause problems in other parts of the system which only work with a specific state.
The common solution to this problem is to use immutable Value Objects.
In object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created
With this implementation whenever a Book is created, it is created with a title, author and a price which can be accessed from any consumer. These values will stay with the book for it's whole lifetime, because there is no way to change them. I tend to trim the word "get" from the getters with value objects, it makes more sense to me to call a book.title(), but that's only one way to do it. The point is to eliminate all the unnecessary setters and put the assignments of required fields up to the constructor.