3

I know that a child cannot reduce the visibility of a non-static method and I understand why it is so.

I've read however that "static method can be hidden through its redeclaration". I however do not understand how this could be achieved in Java.

Is this really possible? If yes, how to do that (code example) and why was it introduced (it seems to contradict the principle of non-reducing the visibility of the interface)?

13
  • Do you have a reference/link for the 2nd statement? Commented Nov 17, 2014 at 0:47
  • Unless I am getting this wrong, it could very well mean override the static method. When you override, you change only the body of the method - everything else i.e. the return type, method name, and signature remain the same. This is sort or redeclaration. Overloading should also work. Commented Nov 17, 2014 at 0:48
  • 1
    possible duplicate of Strange case of static method override in java Commented Nov 17, 2014 at 0:49
  • 2
    Indeed, Eclipse doesn't allow me to override it, treating it the same way as in case of non-static method. So it is not Eclipse, it is a Java restriction, right? Commented Nov 17, 2014 at 0:52
  • 2
    @infoholic_anonymous Overload then - geeksforgeeks.org/… Also, stop saying "Eclipse doesn't let me override/overload..." Eclipse is a tool. You will have same issue even if you use IntelliJ, Notepad++, whatever. It is a Java Language-related issue. Tools are tools. Commented Nov 17, 2014 at 0:54

4 Answers 4

6

The short answer is: no, it is not possible. You have mixed up some terminology. Hiding has nothing to do with accessibility (which is what you are really asking about, not visibility, which is related to scope and shadowing and is discussed in Chapter 6 of the Java Language Specification (JLS)).

Now for the longer answer. The term overriding applies to instance methods, while the term hiding applies to class (static) methods. From the Java Tutorial topic Overriding and Hiding Methods:

The distinction between hiding a static method and overriding an instance method has important implications:

  • The version of the overridden instance method that gets invoked is the one in the subclass.
  • The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.

Some of the other answers here provide incorrect examples about method hiding, so let's go back to the JLS, this time to §8.4.8:

Methods are overridden or hidden on a signature-by-signature basis.

That is, to override or hide a method in the parent class, the subclass must define a method with the same signature—basically, the same number and type of arguments (although generics and type erasure makes the rules a little more complicated than that). There are also rules about return types and throws clauses, but those seem irrelevant to this question.

Note that you can define a method in a subclass with the same name as a method in the parent class (or in an implemented interface) but with different number or type of arguments. In that case, you are overloading the method name and neither overriding nor hiding anything; the subclass method is a new method, pretty much independent of the inherited method(s). (There is an interaction when the compiler has to match methods to method calls, but that's about it.)

Now to your question: the terms accessibility and hiding (as well as visibility) are independent concepts in Java. There is, as you put it, a "principle" that there is simply no way for a subclass to reduce the accessibility of an inherited method. This applies regardless of whether you are overriding an instance method or hiding a class method. From the JLS §8.4.8.3:

The access modifier (§6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:

  • If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.

  • If the overridden or hidden method is protected, then the overriding or hiding method must be protected or public; otherwise, a compile-time error occurs.

  • If the overridden or hidden method has default (package) access, then the overriding or hiding method must not be private; otherwise, a compile-time error occurs.

In summary, the fact that a static method can be hidden has nothing to do with changing the accessibility of the method.

Sign up to request clarification or add additional context in comments.

Comments

1

Based on hagubear's valuable comments, it seems that the author of a statement meant hiding a method through overloading it with a method having the same declaration.

Quoting this link:

We can declare static methods with same signature in subclass, but it is not considered overriding as there won’t be any run-time polymorphism. (...) If a derived class defines a static method with same signature as a static method in base class, the method in the derived class hides the method in the base class.

Thus, defining a method in a child class having exact same declaration effectively hides the original method in child. However, as in case of fields, casting to the parent will restore the original access.

Sample code:

public class Test { public static void main( String[] args ) { B b = new B(); A a = b; b.f(); // "Access somewhat denied" a.f(); // "f()" } } class A { public static void f() { System.out.println("f()"); } } class B extends A { // *must* be public public static void f() { System.out.println("Access somewhat denied"); } } 

1 Comment

Nicely expressed. I like this better than my earlier answer ;)
0

So I created a trivial test; IntelliJ indeed rejected it... and Yes, I know "it's a tool...but one I trust". In any case, I went to javac, which emitted the same ERROR:

Error:(...) java: ...Concrete.java:5: doSomethingStatic() in ...Concrete cannot override doSomethingStatic() in ...Base; attempting to assign weaker access privileges; was public 

Based on this, and our skepticism in general, I suggest the error is in your documentation.

Below is my sample code, fairly definitive I think. It barfs at the protected.

public class Base { public static void doSomethingStatic(){} } public class Concrete extends Base { protected static void doSomethingStatic(){} } 

Comments

-2

It can be hidden by an overloaded redeclaration in a derived class:

class Base { public static void doSomethingStatic(){} } class Derived extends Base { public static void doSomethingStatic(String arg){} } 

but only hidden to people who try to access it via the derived class.

3 Comments

This is not an example of hiding anything. The doSomethingStatic method in Derived does not have the same signature as the method in Base--they have different argument lists.
It is 'hiding' in the sense defined by the JLS, folks. There isn't any other. And that is what the question is about. @TedHopp
It is not "hiding" in the sense of the JLS. From the JLS §8.4.8.2 (emphasis added): "If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible to code in C." In your example, doSomethingStatic() in Base is still accessible from code in Derived because the args are different. Nothing is hidden.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.