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

Pokechu22
  • 4,984
  • 9
  • 37
  • 62
infoholic_anonymous
  • 969
  • 3
  • 12
  • 34
  • Do you have a reference/link for the 2nd statement? – Hovercraft Full Of Eels Nov 17 '14 at 00: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. – ha9u63a7 Nov 17 '14 at 00:48
  • @HovercraftFullOfEels Unfortunately no, it comes from the university materials I've come by and these aren't written in English. – infoholic_anonymous Nov 17 '14 at 00:49
  • 1
    possible duplicate of [Strange case of static method override in java](http://stackoverflow.com/questions/10297252/strange-case-of-static-method-override-in-java) – Tom Nov 17 '14 at 00:49
  • @hagubear: you can't "override" a static method. – Hovercraft Full Of Eels Nov 17 '14 at 00:50
  • 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? – infoholic_anonymous Nov 17 '14 at 00:52
  • 2
    @infoholic_anonymous Overload then - http://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/ 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. – ha9u63a7 Nov 17 '14 at 00:54
  • @hagubear: I didn't mean for you to delete your [recent answer](http://stackoverflow.com/a/26963891/522444) to the other question, rather to just add an explanation to it. Explanations and concepts are valuable, often more so than code. – Hovercraft Full Of Eels Nov 17 '14 at 00:56
  • @HovercraftFullOfEels I saw a comment which made my effort useless anyway - also, let's not confuse this OP here as he will think "I got an answer and it got deleted?" lol – ha9u63a7 Nov 17 '14 at 00:57
  • @hagubear: a correct answer is much better than a comment. Please fix it so I can up-vote it. – Hovercraft Full Of Eels Nov 17 '14 at 00:58
  • @infoholic_anonymous I believe your question has probably been addressed [here](http://stackoverflow.com/questions/2223386/why-doesnt-java-allow-overriding-of-static-methods). This might not be identical, but very close to your issue. – ha9u63a7 Nov 17 '14 at 01:02
  • @hagubear Thanks for the link. I guess an excerpt from it solves the question and is what the author of the statement in question meant. Here is the solution: "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. Hence the answer is ‘No’. 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." – infoholic_anonymous Nov 17 '14 at 01:07
  • @hagubear so maybe you could write a corresponding answer to it so that the question could be marked as solved? – infoholic_anonymous Nov 17 '14 at 01:11

4 Answers4

5

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.

Community
  • 1
  • 1
Ted Hopp
  • 232,168
  • 48
  • 399
  • 521
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");
    }
}
infoholic_anonymous
  • 969
  • 3
  • 12
  • 34
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(){}
}
BrianT.
  • 394
  • 1
  • 6
-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.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 3
    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. – Ted Hopp Nov 17 '14 at 01:59
  • 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 – user207421 Dec 18 '15 at 23:39
  • It is **not** "hiding" in the sense of the JLS. From the [JLS §8.4.8.2](http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#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. – Ted Hopp Dec 19 '15 at 23:06