I was going through this question Is there a way to override class variables in Java? The first comment with 36 upvotes was:
If you ever see a
p
Well, as most of the people have answered:
protected means - 'package-private + visibility to subclasses - the property/behaviour is INHERITED'static means - 'the opposite of instance - it is a CLASS property/behaviour, i.e it is NOT INHERITED'Therefore they are slightly contradictive and incompatible.
However, recently I came up to a use case where it might make sense to use these two together. Imagine that you want to create an abstract class which is a parent for immutable types and it has a bunch of properties which are common to the subtypes. To implement immutability properly and keep readability one might decide to use the Builder pattern.
package X;
public abstract class AbstractType {
protected Object field1;
protected Object field2;
...
protected Object fieldN;
protected static abstract class BaseBuilder> {
private Object field1; // = some default value here
private Object field2; // = some default value here
...
private Object fieldN; // = some default value here
public T field1(Object value) { this.field1 = value; return self();}
public T field2(Object value) { this.field2 = value; return self();}
...
public T fieldN(Object value) { this.fieldN = value; return self();}
protected abstract T self(); // should always return this;
public abstract AbstractType build();
}
private AbstractType(BaseBuilder> b) {
this.field1 = b.field1;
this.field2 = b.field2;
...
this.fieldN = b.fieldN;
}
}
And why protected static ? Because I want a non-abstract subtype of AbstactType which implements its own non-abstract Builder and is located outside package X to be able to access and reuse the BaseBuilder.
package Y;
public MyType1 extends AbstractType {
private Object filedN1;
public static class Builder extends AbstractType.BaseBuilder {
private Object fieldN1; // = some default value here
public Builder fieldN1(Object value) { this.fieldN1 = value; return self();}
@Override protected Builder self() { return this; }
@Override public MyType build() { return new MyType(this); }
}
private MyType(Builder b) {
super(b);
this.fieldN1 = b.fieldN1;
}
}
Of course we can make the BaseBuilder public but then we come to another contradictory statements:
So in both cases with protected static and public builder of an abstract class we combine contradictory statements. It is a matter of personal preferences.
However, I still prefer the public builder of an abstract class because the protected static to me feels more unnatural in a OOD and OOP world !