Why we should not use protected static in java

前端 未结 8 2010
醉梦人生
醉梦人生 2020-11-29 17:01

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

8条回答
  •  夕颜
    夕颜 (楼主)
    2020-11-29 17:35

    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:

    • We have a non-instantiatable class (abstract)
    • We provide a public builder for it

    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 !

提交回复
热议问题