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

Zee*_*han 115 java oop inheritance static protected

我正在经历这个问题有没有办法在Java中覆盖类变量? 36条赞成票的第一条评论是:

如果你看过protected static,跑.

任何人都可以解释为什么protected static不赞成?

Tim*_*m B 79

这比直接问题更具风格性.它表明你没有正确地思考课程的内容.

想想是什么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;
    }
}
Run Code Online (Sandbox Code Playgroud)

你会看到结果:

test
changed
Run Code Online (Sandbox Code Playgroud)

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

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

  • @spudone但单元测试通常放在同一个包中.要授予他们访问权限,您只需使用默认(包)访问级别.受保护也可以访问子类,这不是单元测试所必需的或相关的. (3认同)
  • 你们都被遗产继承了.看到这种情况的典型情况是有人想要包访问而不公开它(例如单元测试). (2认同)
  • "*扩展类可以修改行为*"这将违反Liskov Subsitution原则.子类不应该修改它的超类型的行为.这属于整个"一个正方形不是一个矩形"的论点:调整超类(`Rectangle`)来调整宽度/高度以确保相等(对于`Square`)将产生不希望的结果如果你要用每个超类替换它的子类型的一个实例. (2认同)

Vin*_*igh 31

它不赞成因为它是矛盾的.

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

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

我能找到这个有用的唯一情况是,如果你是宣称应该用于启动应用程序(如JavaFX的的一类Application#launch,只希望能够从一个子类启动,如果这样做,确保方法也final给不允许隐藏.但这不是"常态",并且可能通过添加新方法来启动应用程序来防止增加更多复杂性.

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

  • 我不明白`static`会如何消除继承它的意图.因为我在另一个包中的子类仍然要求super的字段被"protected"访问,即使它是`static`.`package-private`无法帮助 (4认同)
  • 我最初有一个带有一些`private static` util函数的类,但我认为有人可能希望从我的类中改进或自定义,这些util函数也可以为它们提供方便.`public`可能不合适,因为util方法不适用于我的类实例的用户.你能帮我找出一个好的设计而不是`protected`吗?谢谢 (3认同)

Mar*_*o13 13

我没有看到为什么这应该不赞成的特殊原因.可能总是存在实现相同行为的替代方案,并且取决于实际结构,这些替代方案是否比受保护的静态方法"更好".但是受保护的静态方法至少可以合理的一个例子如下:

(编辑分成单独的包,以使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;
    }
}
Run Code Online (Sandbox Code Playgroud)

源于此:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一个派生类:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

protected static修改肯定可以在这里有道理:

  • 方法可以是static,因为它们不依赖于实例变量.它们不是直接用作多态方法,而是"实用"方法,它们提供作为更复杂计算的一部分的默认实现,并充当实际实现的"构建块".
  • 方法不应该是public,因为它们是一个实现细节.他们不能private因为他们应该被扩展类调用.它们也不能具有"默认"可见性,因为在其他包中扩展类将无法访问它们.

(编辑:人们可以假设原始评论仅涉及字段,而不是方法 - 然而,它太过笼统)

  • @Thomas当然,在这种情况下,这也是可能的.一般来说:这当然是部分主观的,但我的经验法则是:当一个方法不打算以多态方式使用,并且它可以是静态的,那么我将它设为静态.与使其成为"final"相比,它不仅清楚地表明该方法不是为了被覆盖,而且*另外*使读者清楚该方法不使用实例变量.如此简洁:没有理由*不*让它静止. (2认同)

Boh*_*ian 7

静态成员不是继承的,和受保护成员只对亚类(和当然包含类)可见,因此protected static具有相同的可见性static,这表明由编码器的误解.

  • 嗯......不.package private和`protected`不一样.如果你只是说`static`,那么该字段只对同一个包中的子类可见. (2认同)
  • @AaronDigulla `protected static` 允许访问*在包内*或*从子类*。将变量设置为静态会消除子类化的意图,只留下从包内访问的意图。 (2认同)

x4u*_*x4u 5

实际上,根本没有什么错protected static。如果您确实想要包和声明类的所有子类可见的静态变量或方法,请继续进行操作protected static

有些人通常避免使用protected各种原因,有些人认为非最终static变量应该通过各种手段来避免(我个人后者在一定程度上同情),所以我猜的组合protectedstatic必须看坏^ 2到那些属于这两个群体。