Why we should not use protected static in java

70,484

Solution 1

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

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.

Solution 2

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.

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

Solution 3

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)

Solution 4

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.

Solution 5

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.

Share:
70,484
Zeeshan
Author by

Zeeshan

Updated on June 12, 2020

Comments

  • Zeeshan
    Zeeshan almost 4 years

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

    If you ever see a protected static, run.

    Can anyone explain why is a protected static frowned upon?

    • VGR
      VGR almost 10 years
      There's nothing wrong with a protected static field, as long as it's final. A mutable static field shared across classes is definitely cause for worry. Multiple classes updating a static field is not likely to be reliable or easy to follow, especially since the presence of any protected field or method implies that the class is meant to be extended by classes in other packages, possibly classes not under the control of the author of the class containing the protected field.
    • Zeeshan
      Zeeshan almost 10 years
      @VGR, final doesn't means the field is immutable. You can always modify the object referenced by a final reference variable.
    • Dioxin
      Dioxin almost 10 years
      @VGR I disagree. The ONLY reason you would make a static variable is to have access to it from within another package only by inherience, and access to a single field should NOT be the reason for inheritence. It's a flawed design, IMO, and if you resort to that, you should probably rethink your application's structure. That's just my opinion though.
    • VGR
      VGR almost 10 years
      @LoneRider You're right. I was thinking immutable, and final certainly doesn't guarantee that.
    • Raj Rajeshwar Singh Rathore
      Raj Rajeshwar Singh Rathore about 5 years
      Even I came here from the same question.
  • hiergiltdiestfu
    hiergiltdiestfu almost 10 years
    Could you please provide a source for your first statement? In a quick test, a protected static int was inherited to and reused in a subclass without a problem.
  • Dioxin
    Dioxin almost 10 years
    Protected static has the same visibility as package-private static, not private static. To add onto this, if you're using protected and static, its best to just remove the access modifier to make it package-private (if your intentions were to make it accessable within the package)
  • Aaron Digulla
    Aaron Digulla almost 10 years
    Uhm ... no. package private and protected are not the same. If you just say static, the field is only visible to subclasses in the same package.
  • Dioxin
    Dioxin almost 10 years
    @AaronDigulla protected static allows access within the package or from a subclass. Making a variable static removes the intentions of subclassing, leaving the only intention being access from within the package.
  • Aaron Digulla
    Aaron Digulla almost 10 years
    @VinceEmigh: Sorry, I was talking to Bohemian. Should have made this more clear.
  • barfuin
    barfuin almost 10 years
    In this case, you should define the default implementations as protected final (since you don't want them overridden), not static. The fact that a method doesn't use instance variables does not mean it should be static (although it can).
  • Marco13
    Marco13 almost 10 years
    @Thomas Sure, in this case, this would also be possible. In general: This certainly is partially subjective, but my rule of thumb is: When a method is not intended to be used polymorphically, and it can be static, then I make it static. In contrast to making it final, it does not only make clear that the method is not intended to be overridden, it additionally makes clear to the reader that the method does not use instance variables. So succinctly: There simply is no reason to not make it static.
  • barfuin
    barfuin almost 10 years
    When a method is not intended to be used polymorphically, and it can be static, then I make it static. - This will get you in trouble when you start using mock frameworks for unit testing. But this leads us to a different topic ...
  • spudone
    spudone almost 10 years
    You guys are hung up on inheritance. The typical case where this is seen is someone wanting package access without making it public (e.g. a unit test).
  • supercat
    supercat almost 10 years
    @VinceEmigh: I would think that making it static would imply that code outside the package would have to include its own derived class in order to access the variable. From a security perspective, if a class allows outside derivation, protected static would be equivalent to public static. On the other hand, protected static would convey something of an implication that outside code unaffiliated with the class shouldn't access the variable, even if it wouldn't be completely prevented from doing so.
  • Tim B
    Tim B almost 10 years
    @spudone but unit tests are generally placed in the same package. To give them access you just use the default (package) access level. Protected gives access to subclasses too which is not required or relevant to unit test.
  • Kamafeather
    Kamafeather over 9 years
    While it answer correctly the question, I don't personally get this line of code: Test.test = "changed";. How can the class Program be able to access the protected attribute test? Shouldn't protected attributes be accessible just from children of the Test class? Or it is because the protected can be seen from "classes in the same package", as quoted above? (sorry if the question is stupid; I almost don't know Java)
  • Tim B
    Tim B over 9 years
    @Kamafeather Protected means that children can see you from different classes and any classes in the same package can see you. So yes Program is in the same package and hence can see the protected member.
  • Kamafeather
    Kamafeather over 9 years
    Thank you for confirming, and excuse me if I came out with this noob question; I usually work in PHP and accessing protected like that would not have sense there.
  • Aobo Yang
    Aobo Yang about 9 years
    I don't understand how would static eliminate the intentions of inheriting it. Because my subclass in another package still require the field of super to be protected to access, even though it's static. package-private cannot help
  • Dioxin
    Dioxin about 9 years
    @AoboYang You're right, which is why some people use protected static. But it's a code smell, hence the "run" part. Access modifiers and inheritance are two different subjects. Yes, you won't be able to access a static member from a super class if it was package-private. But you shouldn't rely on inheritance to reference static fields in the first place; it's a sign of poor design. You'll notice attempts at overriding static methods give no results, which is a clear sign that inheritance is not class based. If you need access outside of the class or package, it should be public
  • Aobo Yang
    Aobo Yang about 9 years
    I have a class with some private static util functions at first, but I think someone may want to improve or customize from my class and these util functions may also provide convenience to them. public may not be appropriate since util methods are not for the user of the instances of my class. Could you help me figure out a good design instead of protected? Thanks
  • Dioxin
    Dioxin about 8 years
    "the extending class could then modify the behavior" This would violate the Liskov Subsitution principle. A subclass should not modify the behavior of it's supertype. This falls under the whole "a square is not a rectangle" argument: adjusting the superclass (Rectangle) to adjust width/height to ensure equality will (for Square) will produce undesired results if you were to replace every supertype with an instance of it's subtype.
  • Tim B
    Tim B about 8 years
    @VinceEmigh I'm not sure what you are talking about? "the extending class could then modify the behavior" doesn't appear in my answer...
  • Dioxin
    Dioxin about 8 years
    "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" A bit hidden, but it's in there. The code example also expresses the statement
  • Tim B
    Tim B about 8 years
    @VinceEmigh Oh I see what you mean. Yes it's a bad idea. I was trying to think of any possible case where you might use the two modifiers together and have legitimate (if badly designed) code and that was all I could come up with.
  • Eugene
    Eugene over 6 years
    @Marco13 there's also the case when you make something protected, not to show inheritance, but to keep it under a single package - not exposed. I guess sealed interfaces would become helpful in this manner when they will in java
  • Marco13
    Marco13 over 6 years
    @Eugene That comment irritates me a bit. Package-visibility can be achieved without any modifier, whereas protected means "Inheriting classes (even in different packages)"...
  • Eugene
    Eugene over 6 years
    @Marco13 you're right, should have made this a better one. I was a referring to something along the lines of @VisibleForTesting...
  • Cecilia
    Cecilia over 4 years
    In that link, it says 'Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to.' ,which is contradict from this question, any thoughts?
  • Dioxin
    Dioxin over 4 years
    @TimB That's sounds like encouraging sloppy code, which I doubt is your intention. It would be nice if you updated your answer, as I've had a few students link me to your post, just for me to link them to your comment. Could keep the upvotes while encouraging sturdier/clearer code.
  • Tim B
    Tim B over 4 years
    @VinceEmigh Better?
  • TomasMolina
    TomasMolina almost 2 years
    protected is an access modifier so it is about class/method/variables access privilege whereas static is about inheritance. Another attribute of a static is that it can be consumed without instantiate an object which is handy. If the method is protected but not static it cannot be consumed without instantiate an object. I see use cases and not mislead when reading the code. Use it in combination with final on variables.