Firstly - the builder pattern is not inherently thread unsafe. I am not sure how you are concluding that it is. Each thread that intends to use the builder will create its own Builder
object, populate it in Joshua Bloch's pragmatic and beautiful way and use it to construct the object. There are no static
variables being affected anywhere in that mechanism, there is no thread unsafety unless you introduce it yourself.
Your concern about validation is - in my humble opinion - a gross pre-optimisation that produces hideously contrived and horribly bloated code. There is no reason to try to avoid validation just because you know the data is valid. Validation is almost always trivial and often takes little more that a few instructions. By bloating the class with these horrible static validation methods you are probably adding thousands of times more cpu cycles just to load this bloated code than you are saving by avoiding the validation.
Compare your contrived and bloated code with this lucid, succinct and patently correct and thread safe code and see what I mean:
public class Thing {
public final String name;
public final int age;
public Thing() {
this(new Thing.Builder());
}
private Thing(Thing.Builder builder) {
name = builder.name;
age = builder.age;
}
public static class Builder {
private String name = null;
private int age = -1;
public Builder() {
name("Broom Hilda");
age(127);
}
public Builder name(String name) {
if (name == null || name.length() == 0) {
throw new IllegalArgumentException("Thing.Builder.name (" + name + ") is null or empty.");
}
this.name = name;
return this;
}
public Builder age(int age) {
if (age < 0) {
throw new IllegalArgumentException("Thing.Builder.age (" + age + ") is negative.");
}
this.age = age;
return this;
}
public Thing build() {
return (new Thing(this));
}
}
}