A few additional thoughts on the

"Half-Bean" technique
.  Brian says:

If I add a final instance variable to Album and forget to set it in the
constructor, the code won’t compile.

Mmmh, yes, but you need to remember to use "final".  And also not to
assign it directly in the declaration.  If you don’t religiously do these
two things (I don’t know about you, but I pretty much only use "final" on
constants), my original complaint applies:  you have no way to remember you
need to update the Builder class every time the main class changes.

On a slightly different topic:

Making Strings immutable was a wonderful choice

I wonder about that.

One of the main reasons why String is immutable is performance.  While trying to make Java
faster, the designers pushed an optimization decision on us, poor programmers,
who are now paying a dear price.  String is immutable, but the fact is that
we need mutable strings on a daily basis.  How did the Java designers solve
this problem?  By silently introducing StringBuffer objects whenever the
operator "+" is applied
to a String.

The consequence of this choice is sadly obvious:  the #1 tip
you see in Java performance books is "Use StringBuffer to manipulate strings,
not String".

Making String immutable was a very poor design decision, because in people’s
minds, a String object is mutable.  Always was, always will be.  It
would have been much more realistic to call the current String class "ConstString"
and StringBuffer, "String".  At least this naming obeys the principle of
least surprise.