为什么我们不应该在 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
Why we should not use protected static in java
提问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 static
frowned 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 static
means:
想想是什么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 protected
means:
想想是什么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 Test2
is able to access the static member test
from Test
without 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
是能够访问静态成员test
从Test
无需限定名称-但它没有继承或让自己的副本。它正在查看内存中完全相同的对象。
回答by Bohemian
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.
静态成员不会被继承,受保护的成员只对子类(当然还有包含的类)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 protected
clearer)
(编辑拆分成单独的包,使使用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 static
modifier 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 beprivate
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.
- 方法可以是
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 protected
implies it will be used within the packageor it will be inherited within a subclass.
创建一个变量protected
意味着它将在包中使用或将在子类中继承。
Making the variable static
makes 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-private
for 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 final
to 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 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^2to those that belong to both groups.
有些人一般protected
出于各种原因避免使用,有些人认为static
应该尽量避免使用非最终变量(我个人在某种程度上同情后者),所以我猜protected
和static
必须的组合对那些看起来很糟糕^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:
好吧,正如大多数人所回答的那样:
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'
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 abstract
class 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 AbstactType
which implements its own non-abstract Builder and is located outside package X
to 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 BaseBuilder
public 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 static
and public
builder of an abstract class
we combine contradictory statements. It is a matter of personal preferences.
因此,在 withprotected static
和public
builder 的abstract class
两种情况下,我们都结合了矛盾的陈述。这是个人喜好的问题。
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 !
但是,我仍然更喜欢public
anabstract class
的构建器,因为protected static
在 OOD 和 OOP 世界中,我感觉更不自然!