Can someone please explain me the meaning of the signature of this class –
org.apache.logging.log4j.core.appender
Class RollingFileAppender.Builder<B extends RollingFileAppender.Builder<B>>
as documented – Log4j2 apidocs
I read it as Builder for type B, where B extends the Builder for type B, which confuses me like anything.
Also, this is a static class and it has a constructor as well. Is this normal? Can somebody please share a reference that can help me understand and use this in program?
PS –
About what I am doing here – I am working on modifying log4j code to make it compatible with log4j2, in which there is a RollingFileAppender created using RollingFileAppender constructor in a util class.
>Solution :
Builders usually have a fluent API. I.e. their building methods return the builder class to be able to directly call other building methods. For example, the class in question – RollingFileAppender.Builder – can be used like this:
var appender = builder.withAppend(true).withLocking(true).build();
That means that the building methods (the ones that are prefixed with with in this case) must return the same builder instance. But … If you design a builder class for being subclassed, you have a problem. What type shall the building method return?
Consider the following classes:
abstract class Builder {
abstract Object build();
Builder withProperty(String property) { return this; }
}
class ChildBuilder extends Builder {
Object build() { return new Object(); }
ChildBuilder withChildProperty(String childProperty) { return this; }
}
The actual return type of the build method does not matter for this explanation. The problem now is … you can’t do the following:
var obj = new ChildBuilder()
.withProperty("property")
.withChildProperty("child property") // Compiler error here!
.build();
The return type of withProperty is Builder, and this type does not know about the building method withChildProperty. So you are breaking the fluent API.
The solution: A parameterized builder class! For our example, you do the following:
abstract class Builder<B extends Builder<B>> {
abstract Object build();
B withProperty(String property) { return this; } // Note the return type here.
}
final class ChildBuilder extends Builder<ChildBuilder> {
Object build() { return new Object(); }
ChildBuilder withChildProperty(String childProperty) { return this; }
}
Now you can do the code as I mentioned above.