为什么我们不应该在 Java 中使用 protected static

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24289070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 11:19:00  来源:igfitidea点击:

Why we should not use protected static in java

javaoopinheritancestaticprotected

提问by Zeeshan

I was going through this question Is there a way to override class variables in Java?The first comment with 36 upvotes was:

我正在研究这个问题有没有办法覆盖 Java 中的类变量?获得 36 票的第一条评论是:

If you ever see a protected static, run.

如果您看到protected static,请运行。

Can anyone explain why is a protected staticfrowned upon?

谁能解释为什么protected static不受欢迎?

采纳答案by Tim B

It's more a stylistic thing than a direct problem. It suggests that you haven't properly thought through what is going on with the class.

这与其说是一个直接的问题,不如说是一个风格问题。这表明你没有正确考虑课堂上发生的事情。

Think about what staticmeans:

想想是什么static意思:

This variable exists at class level, it does not exist separately for each instance and it does not have an independent existence in classes which extend me.

这个变量存在于类级别,它不单独存在于每个实例中,并且它在扩展 me 的类中没有独立存在

Think about what protectedmeans:

想想是什么protected意思:

This variable can be seen by this class, classes in the same package and classes which extend me.

这个变量可以被这个类、同一个包中的类和扩展 me 的类看到。

The two meanings are not exactly mutually exclusive but it is pretty close.

这两种含义并不完全相互排斥,但非常接近。

The only case I can see where you might use the two together is if you had an abstract class that was designed to be extended and the extending class could then modify the behavior using constants defined in the original. That sort of arrangement would most likely end up very messy though and indicates weakness in the design of the classes.

我可以看到您可以将两者一起使用的唯一情况是,如果您有一个旨在扩展的抽象类,然后扩展类可以使用原始类中定义的常量修改行为。不过,这种安排很可能最终会非常混乱,并表明类的设计存在弱点。

In most cases it would be better to have the constants as public since that just makes everything cleaner and allows the people sub-classing more flexibility. Quite apart from anything else in many cases composition is preferable to inheritance, while abstract classes force inheritance.

在大多数情况下,将常量设为公开会更好,因为这只会让一切变得更干净,并允许人们更灵活地进行子类化。在许多情况下,组合比继承更可取,而抽象类强制继承。

To see one example of how this could break things and to illustrate what I mean by the variable not having an independent existence try this example code:

要查看这如何破坏事物的一个示例并说明我所说的变量不具有独立存在的含义,请尝试以下示例代码:

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;
    }
}

You will see the results:

你会看到结果:

test
changed

Try it yourself at: https://ideone.com/KM8u8O

亲自尝试:https: //ideone.com/KM8u8O

The class Test2is able to access the static member testfrom Testwithout needing to qualify the name - but it does not inherit or get its own copy. It is looking at the exact same object in memory.

Test2是能够访问静态成员testTest无需限定名称-但它没有继承或让自己的副本。它正在查看内存中完全相同的对象。

回答by Bohemian

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

静态成员不会被继承,受保护的成员只对子类(当然还有包含的类)protected static可见,所以 a 与具有相同的可见性static,暗示编码人员的误解。

回答by Marco13

I don't see a particular reason why this should be frowned upon. There may always be alternatives to achieve the same behavior, and it will depend on the actual achitecture whether these alternatives are "better" than a protected static method or not. But one example where a protected static method would be reasonable, at least, could be the following:

我看不出有什么特别的理由不赞成这样做。可能总是有实现相同行为的替代方案,并且这些替代方案是否比受保护的静态方法“更好”取决于实际架构。但是,受保护的静态方法至少是合理的一个示例可能如下所示:

(Edited to split into separate packages, to make the use of protectedclearer)

(编辑拆分成单独的包,使使用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;
    }
}

Derived from that:

从中得出:

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;
    }
}

Another derived class:

另一个派生类:

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;
    }
}

The protected staticmodifier can certainly be justified here:

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 implementationsthat 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 privatebecause 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.
  • 方法可以是static,因为它们不依赖于实例变量。它们不打算直接用作多态方法,而是提供默认实现的“实用”方法,这些默认实现是更复杂计算的一部分,并用作实际实现的“构建块”。
  • 方法不应该是public,因为它们是实现细节。它们不能,private因为它们应该由扩展类调用。它们也不能具有“默认”可见性,因为其他包中的扩展类将无法访问它们。

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

(编辑:人们可以假设原始评论只提到fields,而不是方法- 然而,它太笼统了)

回答by Mithun Kannoth

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.

使用 Protected 以便它可以在子类中使用。在具体类的上下文中使用时,定义受保护的静态没有逻辑,因为您可以以静态方式访问相同的变量。但是,编译器会警告以静态方式访问超类静态变量。

回答by Vince Emigh

It's frowned upon because it's contradictive.

之所以不赞成,是因为它自相矛盾。

Making a variable protectedimplies it will be used within the packageor it will be inherited within a subclass.

创建一个变量protected意味着它将在包中使用或将在子类中继承

Making the variable staticmakes it a member of the class, eliminating the intentions of inheriting it. This leaves only the intention of being used within a package, and we have package-privatefor that (no modifier).

使变量static成为类的成员,消除了继承它的意图。这只留下了在包中使用的意图,我们有package-private(没有修饰符)。

The only situation I could find this useful for is if you were declaring a class that should be used to launch the application (like JavaFX's Application#launch, and only wanted to be able to launch from a subclass. If doing so, ensure the method is also finalto disallow hiding. But this is not "the norm", and was probably implemented to prevent adding more complexity by adding a new way to launch applications.

我能找到这个有用的唯一情况是,如果你是宣称应该用于启动应用程序(如JavaFX的的一类Application#launch,只希望能够从一个子类的推出。如果这样做,确保方法也final给禁止隐藏。但这不是“规范”,可能是为了防止通过添加新的应用程序启动方式来增加复杂性。

To see the access levels of each modifier, see this: The Java Tutorials - Controlling Access to Members of a Class

要查看每个修饰符的访问级别,请参阅:Java 教程 - 控制对类成员的访问

回答by x4u

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.

其实没有什么根本性的错误protected static。如果您真的想要一个对包和声明类的所有子类可见的静态变量或方法,请继续并制作它protected static

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

有些人一般protected出于各种原因避免使用,有些人认为static应该尽量避免使用非最终变量(我个人在某种程度上同情后者),所以我猜protectedstatic必须的组合对那些看起来很糟糕^2属于这两个群体。

回答by Aelphaeis

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.

有没有错protected static。许多人忽略的一件事是,您可能希望为在正常情况下不想公开的静态方法编写测试用例。我注意到这对于在实用程序类中为静态方法编写测试特别有用。

回答by egelev

Well, as most of the people have answered:

好吧,正如大多数人所回答的那样:

  • protectedmeans - 'package-private + visibility to subclasses - the property/behaviour is INHERITED'
  • staticmeans - 'the opposite of instance - it is a CLASS property/behaviour, i.e it is NOT INHERITED'
  • protected意味着 - '包私有 + 子类的可见性 - 属性/行为是继承的'
  • static意味着 - '与实例相反 - 它是一个类属性/行为,即它不是继承的'

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 abstractclass which is a parent for immutabletypes and it has a bunch of properties which are common to the subtypes. To implement immutabilityproperly and keep readabilityone might decide to use the Builderpattern.

但是,最近我想到了一个用例,其中将这两者结合使用可能是有意义的。想象一下,你想创建一个abstract类,它是不可变类型的父类,它有一堆子类型共有的属性。为了正确实现不变性并保持可读性,人们可能会决定使用Builder模式。

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 AbstactTypewhich implements its own non-abstract Builder and is located outside package Xto be able to access and reuse the BaseBuilder.

为什么protected static?因为我想要一个非抽象子类型,AbstactType它实现自己的非抽象生成器并且位于外部package X以便能够访问和重用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 BaseBuilderpublic but then we come to another contradictory statements:

当然,我们可以BaseBuilder公开,但随后我们又得出了另一个矛盾的陈述:

  • We have a non-instantiatable class (abstract)
  • We provide a public builder for it
  • 我们有一个不可实例化的类(抽象)
  • 我们为它提供了一个公共构建器

So in both cases with protected staticand publicbuilder of an abstract classwe combine contradictory statements. It is a matter of personal preferences.

因此,在 withprotected staticpublicbuilder 的abstract class两种情况下,我们都结合了矛盾的陈述。这是个人喜好的问题。

However, I still prefer the publicbuilder of an abstract classbecause the protected staticto me feels more unnatural in a OOD and OOP world !

但是,我仍然更喜欢publicanabstract class构建器,因为protected static在 OOD 和 OOP 世界中,我感觉更不自然!