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

时间:2022-09-11 10:35:42

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条upvotes的第一条评论是:

If you ever see a protected static, run.

如果您看到受保护的静态,请运行。

Can anyone explain why is a protected static frowned upon?

任何人都可以解释为什么受保护的静态不受欢迎?

7 个解决方案

#1


64  

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:

想想静态意味着什么:

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.

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

Think about what protected means:

想想保护意味着什么:

This variable can be seen by this class, classes in the same package and classes which extend 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. Even then it's a very feeble reason though as you would still almost certainly be better having the constants as public. That just makes everything cleaner and allows the people sub classing more flexibility.

我可以看到你可以在哪里使用这两者的唯一情况是,如果你有一个设计为扩展的抽象类,然后扩展类可以使用原始中定义的常量修改行为。即使这样,这也是一个非常微弱的原因,因为你几乎肯定会更好地将常数公之于众。这只会让一切变得更加清洁,并且让人们可以更加灵活地进行分类。

To expand and explain the first point - 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 variable.

Test2类能够从Test访问静态成员测试而无需限定名称 - 但它不会继承或获取自己的副本。它正在查看完全相同的变量。

#2


24  

It's frowned upon because it's contradictive.

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

Making a variable protected implies it will be used within the package or it will be inherited within a subclass.

使变量受保护意味着它将在包中使用,或者它将在子类中继承。

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).

使变量成为静态使其成为类的成员,从而消除了继承它的意图。这只留下在包中使用的意图,并且我们有包私有(没有修饰符)。

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,并且只希望能够从子类启动。如果这样做,请确保方法也是最终不允许隐藏。但这不是“常态”,并且可能通过添加新方法来启动应用程序来防止增加更多复杂性。

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

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

#3


11  

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)

(编辑分成单独的包,以使用受保护的清除器)

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:

受保护的静态修饰符当然可以在这里证明:

  • 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)

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

#4


6  

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.

静态成员不是继承的,受保护的成员只对子类(当然还有包含类)可见,因此受保护的静态与static具有相同的可见性,这表明编码器存在误解。

#5


3  

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以便可以在子类中使用。在具体类的上下文中使用时,定义受保护的静态没有逻辑,因为您可以以静态方式访问相同的变量。但是,编译器将发出警告以静态方式访问超类静态变量。

#6


3  

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.

有些人一般会因为各种原因避免使用保护,有些人认为应该尽量避免使用非最终的静态变量(我个人在某种程度上同情后者),所以我想保护和静态的组合必须看起来很糟糕^ 2属于两个组。

#7


0  

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.

保护静态没有任何问题。很多人都忽视的一件事是,您可能希望为静态方法编写测试用例,而这些方法在正常情况下不希望暴露。我注意到这对于在实用程序类中编写静态方法的测试特别有用。

#1


64  

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:

想想静态意味着什么:

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.

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

Think about what protected means:

想想保护意味着什么:

This variable can be seen by this class, classes in the same package and classes which extend 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. Even then it's a very feeble reason though as you would still almost certainly be better having the constants as public. That just makes everything cleaner and allows the people sub classing more flexibility.

我可以看到你可以在哪里使用这两者的唯一情况是,如果你有一个设计为扩展的抽象类,然后扩展类可以使用原始中定义的常量修改行为。即使这样,这也是一个非常微弱的原因,因为你几乎肯定会更好地将常数公之于众。这只会让一切变得更加清洁,并且让人们可以更加灵活地进行分类。

To expand and explain the first point - 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 variable.

Test2类能够从Test访问静态成员测试而无需限定名称 - 但它不会继承或获取自己的副本。它正在查看完全相同的变量。

#2


24  

It's frowned upon because it's contradictive.

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

Making a variable protected implies it will be used within the package or it will be inherited within a subclass.

使变量受保护意味着它将在包中使用,或者它将在子类中继承。

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).

使变量成为静态使其成为类的成员,从而消除了继承它的意图。这只留下在包中使用的意图,并且我们有包私有(没有修饰符)。

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,并且只希望能够从子类启动。如果这样做,请确保方法也是最终不允许隐藏。但这不是“常态”,并且可能通过添加新方法来启动应用程序来防止增加更多复杂性。

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

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

#3


11  

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)

(编辑分成单独的包,以使用受保护的清除器)

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:

受保护的静态修饰符当然可以在这里证明:

  • 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)

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

#4


6  

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.

静态成员不是继承的,受保护的成员只对子类(当然还有包含类)可见,因此受保护的静态与static具有相同的可见性,这表明编码器存在误解。

#5


3  

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以便可以在子类中使用。在具体类的上下文中使用时,定义受保护的静态没有逻辑,因为您可以以静态方式访问相同的变量。但是,编译器将发出警告以静态方式访问超类静态变量。

#6


3  

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.

有些人一般会因为各种原因避免使用保护,有些人认为应该尽量避免使用非最终的静态变量(我个人在某种程度上同情后者),所以我想保护和静态的组合必须看起来很糟糕^ 2属于两个组。

#7


0  

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.

保护静态没有任何问题。很多人都忽视的一件事是,您可能希望为静态方法编写测试用例,而这些方法在正常情况下不希望暴露。我注意到这对于在实用程序类中编写静态方法的测试特别有用。