program tip

왜 우리는 자바에서 protected static을 사용하지 않아야합니까?

radiobox 2020. 7. 29. 08:05
반응형

왜 우리는 자바에서 protected static을 사용하지 않아야합니까?


이 질문을 겪고 있었습니다 .Java에서 클래스 변수를 재정의하는 방법이 있습니까? 36 개의 공감대에 대한 첫 번째 의견은 다음과 같습니다.

을 본 적이 있으면 protected static실행하십시오.

protected static눈살을 찌푸리는 지 설명 할 수 있습니까 ?


직접적인 문제보다는 문체 적입니다. 그것은 당신이 수업에 무슨 일이 일어나고 있는지에 대해 제대로 생각하지 않았 음을 암시합니다.

무엇을 static의미 하는지 생각해보십시오 .

이 변수는 클래스 수준에 존재하며 각 인스턴스에 대해 별도로 존재 하지 않으며 나를 확장하는 클래스에는 독립적으로 존재하지 않습니다 .

무엇을 protected의미 하는지 생각해보십시오 .

이 변수는이 클래스, 동일한 패키지의 클래스 및 나를 확장하는 클래스에서 볼 수 있습니다 .

이 두 가지 의미는 서로 배타적이지는 않지만 꽤 가깝습니다.

두 가지를 함께 사용할 수있는 유일한 경우는 확장하도록 설계된 추상 클래스가 있고 확장 클래스가 원본에 정의 된 상수를 사용하여 동작을 수정할 수있는 경우입니다. 그럼에도 불구하고 상수가 공개적으로 유지되는 것이 거의 확실하기 때문에 매우 약한 이유입니다. 그것은 모든 것을 깨끗하게 만들고 사람들이 하위 분류를보다 유연하게 만듭니다.

첫 번째 요점을 확장하고 설명하려면 다음 예제 코드를 시도하십시오.

public class Program {
    public static void main (String[] args) throws java.lang.Exception {
        System.out.println(new Test2().getTest());
        Test.test = "changed";
        System.out.println(new Test2().getTest());
    }
}

abstract class Test {
    protected static String test = "test";
}

class Test2 extends Test {
    public String getTest() {
        return test;
    }
}

결과가 나타납니다.

test
changed

https://ideone.com/KM8u8O 에서 직접 사용해보십시오.

이 클래스는 Test2정적 멤버에 액세스 할 수 있습니다 test에서 Test이름을 규정 할 필요없이 - 그러나 상속하지 않습니다 또는 자신의 사본을 얻을. 정확히 같은 변수를보고 있습니다.


모순되기 때문에 눈살을 찌푸 렸습니다.

변수를 만들면 패키지 내에서protected 사용 되거나 하위 클래스 내에서 상속됩니다 .

변수를 static만들면 변수 를 클래스의 멤버로 만들어 상속하려는 의도를 제거합니다 . 이것은 패키지 내에서 사용될 의도만을 남기고 , 우리는 그것을 package-private위해 (수정자가 없음) 있습니다.

당신은 자바 FX의 같은 응용 프로그램을 (실행하는 데 사용되어야하는 클래스를 선언한다면 나는이 유용하게 찾을 수있는 유일한 상황은 Application#launch, 단지 서브 클래스에서 발사 할 수있을 싶었다. 그렇게하면, 방법은 또한 보장 final에 허용 안 숨어 . 그러나 이것은 "규범"아니다, 아마도 응용 프로그램을 실행할 수있는 새로운 방법을 추가하여 더 복잡성을 추가하는 것을 방지하기 위해 구현되었다.

각 수정 자의 액세스 레벨을 보려면 다음을 참조하십시오 . Java 학습서-클래스 멤버에 대한 액세스 제어


나는 이것이 눈살을 찌푸리는 특별한 이유를 보지 못했다. 항상 동일한 동작을 달성하기위한 대안이있을 수 있으며, 이러한 대안이 보호 된 정적 방법보다 "더 나은"지 여부에 따라 실제 구조에 따라 달라집니다. 그러나 보호 된 정적 메소드가 합리적 일 수있는 한 가지 예는 다음과 같습니다.

( protected더 명확하게 사용하기 위해 별도의 패키지로 분할하도록 편집 )

package a;
import java.util.List;

public abstract class BaseClass
{
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeDefaultB(list);
    }

    protected static Integer computeDefaultA(List<Integer> list)
    {
        return 12;
    }
    protected static Integer computeDefaultB(List<Integer> list)
    {
        return 34;
    }
}

그것에서 파생 된 :

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassA extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeDefaultA(list)+computeOwnB(list);
    }

    private static Integer computeOwnB(List<Integer> list)
    {
        return 56;
    }
}

다른 파생 클래스 :

package a.b;

import java.util.List;

import a.BaseClass;

abstract class ExtendingClassB extends BaseClass
{
    @Override
    public Integer compute(List<Integer> list)
    {
        return computeOwnA(list)+computeDefaultB(list);
    }

    private static Integer computeOwnA(List<Integer> list)
    {
        return 78;
    }
}

protected static수정 확실히 여기 정당화 될 수 :

  • The methods can be static, because they do not depend on instance variables. They are not intended to be used directly as a polymorphic method, but rather are "utility" methods that offer default implementations that are part of a more complex computation, and serve as "building blocks" of the actual implementation.
  • The methods should not be public, because they are an implementation detail. And they can't be private because they should be called by the extending classes. They also can't have "default" visibility, because then they will not be accessible for the extending classes in other packages.

(EDIT: One could assume that the original comment only referred to fields, and not to methods - then, however, it was too general)


Static members are not inherited, and protected members are only visible to subclasses (and of course the containing class), so a protected static has the same visibility as static, suggesting a misunderstanding by the coder.


Actually there is nothing fundamentally wrong with protected static. If you really want a static variable or method that is visible for the package and all subclasses of the declaring class then go ahead and make it protected static.

Some people generally avoid to use protected for various reasons and some people think non-final static variables should be avoided by all means (I personally sympathize with the latter to some degree), so I guess the combination of protected and static must look bad^2 to those that belong to both groups.


Protected is used so that it can be used in subclasses. There is no logic in defining a protected static when using in the context of concrete classes as you can access the same variable is a static way.However the complier will give a warning to access the super class static variable in a static way.


There is nothing wrong with having protected static. One thing a lot of people are overlooking is that you may want to write test cases for static methods that you don't want to expose under normal circumstances. I've noticed this is particularly useful for writing tests for static method in utility classes.


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<T extends BaseBuilder<T>> {
    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<Builder> {
        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 !

참고URL : https://stackoverflow.com/questions/24289070/why-we-should-not-use-protected-static-in-java

반응형