为什么我们不应该在java中使用受保护的静态
我正在经历这个问题有没有办法在Java中重写类variables? 第36条提案的第一条评论是:
如果您看到
protected static
,请运行。
任何人都可以解释为什么被protected static
皱眉?
这是一个更直接的问题,而不是一个风格的东西。 这表明你没有正确地思考class上发生的事情。
想想什么是static
意思:
这个variables存在于类的层次上,对于每一个实例它都不是单独存在的,它在扩展我的类中没有独立的存在 。
考虑一下protected
手段:
这个variables可以被这个类看到,类在相同的包和类中扩展了我 。
这两个意思不完全相互排斥,但是非常接近。
唯一的情况是我可以看到你们可以在一起使用这两者的情况是,如果你有一个被devise为扩展的抽象类,那么扩展类可以使用原来定义的常量修改行为。 即使如此,这是一个非常微弱的理由,因为你仍然可以将常数公诸于众。 这只是让一切更清洁,让人们分类更灵活。
扩展和解释第一点 – 试试这个例子代码:
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
,而不需要限定名称 – 但它不会inheritance或获取自己的副本。 它看着完全相同的variables。
这是因为它是矛盾的而皱起了眉头。
使variablesprotected
意味着将在包中使用它,否则它将在子类中inheritance 。
使variablesstatic
成为类的成员, 消除了inheritance它的意图 。 这只留下了在一个包中使用的意图,我们有package-private
)(没有修饰符)。
唯一的情况是我发现这个有用的是,如果你声明了一个应该用来启动应用程序的类(比如JavaFX的Application#launch
,并且只希望能够从子类启动,那么确保方法也是final
一个不允许隐藏的东西 ,但这不是“规范”,可能是为了防止通过添加新的方式来启动应用程序而增加更多的复杂性。
要查看每个修饰符的访问级别,请参阅: Java教程 – 控制对类成员的访问
我不明白为什么这个问题应该被忽视。 总是可以有替代scheme来实现相同的行为,这将取决于实际的架构,这些替代scheme是否比受保护的静态方法“更好”。 但是一个例子,一个受保护的静态方法是合理的,至less可以是这样的:
(编辑分成单独的包,使使用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 ab; 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 ab; 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
修改器当然可以在这里certificate:
- 这些方法可以是
static
,因为它们不依赖于实例variables。 它们不是直接用作多态方法,而是提供作为更复杂计算一部分的默认实现的 “实用”方法,并作为实际实现的“构build块”。 - 这些方法不应该是
public
,因为它们是一个实现细节。 而且他们不能是private
因为他们应该由扩展class级来调用。 他们也不能具有“默认”可见性,因为那样他们将不能被其他包中的扩展类访问。
(编辑:人们可以假设原来的评论只是提到领域 ,而不是方法 – 然而,这是太笼统了)
静态成员不是inheritance的,被保护的成员只对子类(当然是包含的类)可见,所以protected static
与protected static
具有相同的可见性,这意味着编码人员的误解。
保护被使用,以便它可以在子类中使用。 当在具体类的上下文中使用时定义受保护的静态方法没有任何逻辑,因为您可以通过静态的方式访问相同的variables。但是,编译器将以静态方式发出警告来访问超类静态variables。
其实protected static
并没有什么根本的错误。 如果你真的想要一个静态variables或方法,可以看到包和声明类的所有子类,然后继续使其保持protected static
。
有些人一般避免使用protected
的各种原因,有些人认为非最终的static
variables应该尽量避免(我个人同情后者在一定程度上),所以我认为protected
和static
的组合必须看起来很糟糕^ 2属于这两个群体。
protected static
没有任何问题。 有很多人忽略了一件事情,那就是你可能想编写静态方法的testing用例,在一般情况下你不想公开这些方法。 我注意到这对于在实用类中编写静态方法的testing特别有用。