The problem is that builders should work particularly well with final fields, but assigning a value to a final field right in the field declaration locks in the value which means we'd have to rewrite those expressions (we can do that), but more to the point it now looks rather unnatural: Someone who isn't intricately familiar with exactly how @Builder works would assume that these fields are somehow just locked into the stated defaults for all instances ever created and will probably scratch their head wondering why the heck the fields even exist if they can only ever hold one value anyway.
That means we either have to introduce 'magic names', like so:
public class Clazz {
private final String val1;
private static final String val1_DEFAULT = "default1";
}
But I don't like magic strings. There's also no way for us to warn unless we establish that _ANY_ variable declaration whose name ends in '_DEFAULT' that isn't in fact a default for a @Builder someplace is worth a warning.
The alternative is a construct roel thought up. A defaults block. This was designed for giving method parameters default values and looks like this:
public void methodDef(String arg1, int arg2) {
defaults: {
arg1 = "Default1";
arg2 = 5;
}
// code of method here
}
But, if we can extend this idea to defaults for fields is unclear. There's such a thing as an initializer which looks similar and is legal as a member of a class directly, but you can't stick a label on those. It would also cause compiler errors (changing final variables, though the defaults block of methods has the same issue if the args are marked final, but that is a class of error that we can prevent (lombok runs before the semantic checks that produce those errors run, so we can fix the code in time to avoid them).
Lack of label really annoys me, though.
You can do this right now with the current version of lombok with the following construct:
@Builder
public class Clazz {
private final String val1;
public static class ClazzBuilder {
private String val1 = "Default1";
}
}
What's going on here is the following rule: Builder will not create that which you already explicitly created, but it will bolt on whatever builder would have added to that thing if you haven't explicitly done so yourself. So, normally, @Builder would have generated an inner class called ClazzBuilder, but you already did this, so it'll skip that part. It also won't create a field named 'val1' in that builder because you did so. But it WILL put a method called 'val1' in there, as well as a 'build' method, and the builder() static method that creates a new instance of ClazzBuilder will also be generated in Clazz itself.