As succinctly described here, overriding private methods in Java is invalid because a parent class's private methods are "automatically final, and hidden from the derived class". My question is largely academic.
How is it not a violation of encapsulation to not allow a parent's private method to be "overridden" (ie, implemented independently, with the same signature, in a child class)? A parent's private method cannot be accessed or inherited by a child class, in line with principles of encapsulation. It is hidden.
So, why should the child class be restricted from implementing its own method with the same name/signature? Is there a good theoretical foundation for this, or is this just a pragmatic solution of some sort? Do other languages (C++ or C#) have different rules on this?
You can't override a private method, but you can introduce one in a derived class without a problem. This compiles fine:
class Base
{
private void foo()
{
}
}
class Child extends Base
{
private void foo()
{
}
}
Note that if you try to apply the #Override annotation to Child.foo() you'll get a compile-time error. So long as you have your compiler/IDE set to give you warnings or errors if you're missing an #Override annotation, all should be well. Admittedly I prefer the C# approach of override being a keyword, but it was obviously too late to do that in Java.
As for C#'s handling of "overriding" a private method - a private method can't be virtual in the first place, but you can certainly introduce a new private method with the same name as a private method in the base class.
Well, allowing private methods to be overwritten will either cause a leak of encapsulation or a security risk. If we assume that it were possible, then we’d get the following situation:
Let's say that there's a private method boolean hasCredentials() then an extended class could simply override it like this:
boolean hasCredentials() { return true; }
thus breaking the security check.
The only way for the original class to prevent this would be to declare its method final. But now, this is leaks implementation information through the encapsulation, because a derived class now cannot create a method hasCredentials any more – it would clash with the one defined in the base class.
That’s bad: lets say this method doesn’t exist at first in Base. Now, an implementor can legitimately derive a class Derived and give it a method hasCredentials which works as expected.
But now, a new version of the original Base class is released. Its public interface doesn’t change (and neither do its invariants) so we must expect that it doesn’t break existing code. Only it does, because now there’s a name clash with a method in a derived class.
I think the question stems from a misunderstanding:
How is it /not/ a violation of encapsulation to not allow a parent's private method to be "overridden" (ie, implemented independently, with the same signature, in a child class)
The text inside the parentheses is the opposite of the text before it. Java does allow you to “independently implement [a private method], with the same signature, in a child class”. Not allowing this would violate encapsulation, as I’ve explained above.
But “to not allow a parent's private method to be "overridden"” is something different, and necessary to ensure encapsulation.
"Do other languages (C++ or C#) have different rules on this?"
Well, C++ has different rules: the static or dynamic member function binding process and the access privileges enforcements are orthogonal.
Giving a member function the private access privilege modifier means that this function can only be called by its declaring class, not by others (not even the derived classes). When you declare a private member function as virtual, even pure virtual (virtual void foo() = 0;), you allow the base class to benefit from specialization while still enforcing the access privileges.
When it comes to virtual member functions, access privileges tells you what you are supposed to do:
private virtual means that you are allowed to specialize the behavior but the invocation of the member function is made by the base class, surely in a controlled fashion
protected virtual means that you should / must invoke the upper class version of the member function when overriding it
So, in C++, access privilege and virtualness are independent of each other. Determining whether the function is to be statically or dynamically bound is the last step in resolving a function call.
Finally, the Template Method design pattern should be preferred over public virtual member functions.
Reference: Conversations: Virtually Yours
The article gives a practical use of a private virtual member function.
ISO/IEC 14882-2003 §3.4.1
Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
ISO/IEC 14882-2003 §5.2.2
The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function isvirtualand is not specified using aqualified-idthen the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression.
A parent's private method cannot be accessed or inherited by a child class, inline with principles of encapsulation. It is hidden.
So, why should the child class be
restricted from implementing its own
method with the same name/signature?
There is no such restriction. You can do that without any problems, it's just not called "overriding".
Overridden methods are subject to dynamic dispatch, i.e. the method that is actually called is selected at runtime depending on the actual type of the object it's called on. With private method, that does not happen (and should not, as per your first statement). And that's what is meant by the statement "private methods can't be overridden".
I think you're misinterpreting what that post says. It's not saying that the child class is "restricted from implementing its own method with the same name/signature."
Here's the code, slightly edited:
public class PrivateOverride {
private static Test monitor = new Test();
private void f() {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
});
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
And the quote:
You might reasonably expect the output to be “public f( )”,
The reason for that quote is that the variable po actually holds an instance of Derived. However, since the method is defined as private, the compiler actually looks at the type of the variable, rather than the type of the object. And it translates the method call into invokespecial (I think that's the right opcode, haven't checked JVM spec) rather than invokeinstance.
It seems to be a matter of choice and definition. The reason you can't do this in java is because the specification says so, but the question were more why the specification says so.
The fact that C++ allows this (even if we use virtual keyword to force dynamic dispatch) shows that there is no inherent reason why you couldn't allow this.
However it seem to be perfectly legal to replace the method:
class B {
private int foo()
{
return 42;
}
public int bar()
{
return foo();
}
}
class D extends B {
private int foo()
{
return 43;
}
public int frob()
{
return foo();
}
}
Seems to compile OK (on my compiler), but the D.foo is not related to B.foo (ie it doesn't override it) - bar() always return 42 (by calling B.foo) and frob() always returns 43 (by calling D.foo) no matter whether called on a B or D instance.
One reason that Java does not allow override the method would be that they didn't like to allow the method to be changed as in Konrad Rudolph's example. Note that C++ differs here as you need to use the "virtual" keyword in order to get dynamic dispatch - by default it hasn't so you can't modify code in base class that relies on the hasCredentials method. The above example also protects against this as the D.foo does not replace calls to foo from B.
When the method is private, it's not visible to its child. So there is no meaning of overriding it.
I apologize for using the term override incorrectly and inconsistent with my description. My description describes the scenario. The following code extends Jon Skeet's example to portray my scenario:
class Base {
public void callFoo() {
foo();
}
private void foo() {
}
}
class Child extends Base {
private void foo() {
}
}
Usage is like the following:
Child c = new Child();
c.callFoo();
The issue I experienced is that the parent foo() method was being called even though, as the code shows, I was calling callFoo() on the child instance variable. I thought I was defining a new private method foo() in Child() which the inherited callFoo() method would call, but I think some of what kdgregory has said may apply to my scenario - possibly due to the way the derived class constructor is calling super(), or perhaps not.
There was no compiler warning in Eclipse and the code did compile. The result was unexpected.
Beyond anything said before, there's a very semantic reason for not allowing private methods to be overridden...THEY'RE PRIVATE!!!
If I write a class, and I indicate that a method is 'private', it should be completely unseeable by the outside world. Nobody should be able access it, override it, or anything else. I simply ought to be able to know that it is MY method exclusively and that nobody else is going to muck with it or depend on it. It could not be considered private if someone could muck with it. I believe that it's that simple really.
A class is defined by what methods it makes available and how they behave. Not how those are implemented internally (e.g. via calls to private methods).
Because encapsulation has to do with behavior and not implementation details, private methods have nothing to do with the idea encapsulation. In a sense, your question makes no sense. It's like asking "How is putting cream in coffee not a violation of encapsulation?"
Presumably the private method is used by something that is public. You can override that. In doing so, you've changed behavior.
Related
This question already has answers here:
Why is it that we cannot override static and final methods? [duplicate]
(5 answers)
Closed 1 year ago.
In Java, what is the actual reason behind the inability to write a method in a sub class which has the same name as a final method in the super class? (Please note that I am not trying to override the method, this is why I have put the keyword final.)
Please see the example below:
class A {
public final void method() {
System.out.println("in method A");
}
}
class B extends A {
public void method() {
System.out.println("in method B");
}
}
The problem is expressed as "'method()' cannot override 'method()' in 'A'; overridden method is final" in the IDE; however, I would like to understand what it is about this situation that leads the compiler to fail.
Because in java, overriding isn't optional.
Names of methods at the class level.
At the class level (as in, what is in a class file, and what a JVM executes), method names include their return type and their parameter types (and, of course, the name). At the JVM level, varargs doesn't exist (it's an array instead), generics do not exist (they are erased for the purposes of signature), and the throws clause isn't a part of the story. But other than that, this method:
public void foo(String foo, int bar, boolean[] baz, long... args) throws Exception {}
turns into this name at the class file level:
foo(Ljava/lang/String;I[Z[J)V
which seems like gobbledygook, but [ is 'array of', the primitives get one letter each (Z for boolean, J for longs, I for integer), V is for void, and L is for: Object type. Now it makes sense.
That really is the method name at the class level, effectively (well, we call this its signature). ANY invocation of a method in java, at the class level, always uses the complete signature. This means javac simply cannot compile a method call unless it actually knows the exact method you're invoking, which is why javac doesn't work unless you have the full classpath of everything you're calling available as you compile.
Overriding isn't optional!
At the class level, if you define a method whose full signature matches, exactly, a signature in your parent class, then it is overriding that method. Period. You can't not. #Override as an annotation doesn't affect this in the slightest (That annotation merely causes the compiler to complain if you aren't overriding anything, it's compiler-checked documentation, that's all it is).
javac goes even further
As a language thing, javac will make bridges if you want to tighten the return type. Given:
class Parent {
Object foo() { return null; }
}
class Child extends Parent {
String foo() { return null; }
}
Then at the class level, the full signature of the one method in Parent is foo()Ljava/lang/Object; whereas the one in Child has foo()Ljava/lang/String; and thus these aren't the same method and Child's foo would appear not to be overriding Parent's foo.
But javac intervenes, and DOES make these override. It does this by actually making 2 methods in Child. You can see this in action! Write the above, compile it, and run javap -c -v on Child and you see these. javac makes 2 methods: Both foo()Ljava/lang/String; and foo()Ljava/lang/Object; (which does have the same signature and thus overrides, by definition, Parent's implementation). That second one is implemented as just calling the 'real' foo (the one returning string), and gets the synthetic flag.
Final is what it is
Which finally gets to your problem: Given that final says: I cannot be overridden, then, that's it. You've made 2 mutually exclusive rules now:
Parent's foo cannot be overriden
Child's foo, by definition (because its signatures match), overrides Parent's foo
Javac will just end it there, toss an error in your face, and call it a day. If you imagined some hypothetical javac update where this combination of factors ought to result in javac making a separate method: But, how? At the class level, same signature == same method (it's an override), so what do you propose? That java add a 0 to the end of the name?
If that's the plan, how should javac deal with this:
Parent p = new Child();
p.foo();
Which foo is intended there? foo()Ljava/lang/Object; from Parent, or foo0()L/java/Object; from child?
You can write a spec that gives an answer to this question (presumably, here it's obvious: Parent's foo; had you written Child c = new Child(); c.foo(); then foo0 was intended, but that makes the language quite complicated, and for what purpose?
The java language designers did not think this is a useful exercise and therefore didn't add this complication to the language. I'm pretty sure that was clearly the right call, but your opinion may of course be different.
Final means not just that you can’t override it, it means you can’t work around having that method get called.
When you subclass the object, if you could make a method that shadows that final method, then you could prevent the superclass method from functioning, or substitute some other functionality than what the user of the object would expect. This would allow introducing malicious code and would defeat the purpose of making methods final.
In your case it sounds like making the superclass method final may not have been the best choice.
Eg
class Abc{
public void fun()
{
System.out.println("public method") ;
}
#Override
public String toString()
{
// "has to be public method but the access is default because of the class access";
return super.toString();
}
}
In the above Eg - fun method access is public but the class access is default hence what is the use of having the method public rather than default because it cannot be access without creating object.
In the same way the toString method has to be public since (overriding cannot restrict the access). But it is already getting restricted since the class access is default
My Basic question is
What is the use of having a less restricted method in a more restricted class?
My Basic question is What is the use of having a less restricted method in a more restricted class?
There are several purposes related to inheritance and polymorphism. The biggest of those is probably that methods that override superclass methods or implement interface methods cannot be more restricted than the method they override. In this regard, I note that you express a possible misconception when you say:
the toString method has to be public since (overriding cannot restrict the access). But it is already getting restricted since the class access is default
That class Abc has default access does not prevent any other class from having references to instances of Abc or from invoking the public methods of that class. The declared type of any such reference will be a supertype of class Abc, but the implementation invoked will be that provided by Abc.
Additionally, there is the question of signaling intent. It is helpful to view the access specified for class members to be qualified by the access level of the class. Thus, declaring fun() to be public says that it can be accessed by everyone who can access an instance of Abc. This is somewhat useful in its own right, but it also turns out to be especially useful if the access level of the class is ever changed. If the class's designer chose member access levels according to this principle, then those do not need to be revisited under these circumstances.
On its face?
Absolutely no purpose whatsoever. It's measurable (you can use reflection to fetch a java.lang.reflect.Method object that represents that method, and you can ask it if it is public, and the answer would be 'yes', but it doesn't actually change how accessible that method is.
However, taking a step back and thinking about the task of programming in its appropriate light, which includes the idea that code is usually a living, breathing idea that is continually updated: Hey, your class is package private today. Maybe someone goes in and makes it public tomorrow, and you intended for this method to be just as public as the type itself if ever that happens.
Specifically in this case, you're overriding a method. Java is always dynamic dispatch. That means that if some code has gotten a hold of an instance of this class (Created with new Abc()), and that code is not in this package, that they can still invoke this method.
Let's see it in action:
package abc;
class Abc {
#Override public String toString() { return "Hello"; }
}
public class AbcMaker {
public Object make() { return new Abc(); }
}
Note that here AbcMaker is public and make() can be invoked just fine from outside code; they know what Object is, and Abc is an Object. This lets code from outside the abc package invoke and obtain Abc instances, even though Abc is package private. This is fine.
They can then do:
package someOtherPackage;
class Test {
public void foo() {
System.out.println(new AbcMaker().make().toString());
}
}
And that would print Hello, as expected - that ends up invoking the toString defined in your package private class, invoked from outside the package!
Thus, we come to a crucial conclusion:
That toString() method in your package private class is ENTIRELY PUBLIC.
It just is. You can't override a method and make it less accessible than it is in your parent type, because java is covariant, meaning any X is a valid standin for Y, if X is declared as X extends Y. if Y has public toString, then X's can't take that away, as all Xs must be valid Ys (and Ys have public toString methods, therefore Xs must also have this).
Thus, the compiler is forcing you here. The banal reason is 'cuz the spec says so', but the reason the spec says this is to make sure you, the programmer, are not confused, and that what you type and write matches with reality: That method is public, it has to be, so the compiler will refuse to continue unless you are on the same page as it and also say so.
As succinctly described here, overriding private methods in Java is invalid because a parent class's private methods are "automatically final, and hidden from the derived class". My question is largely academic.
How is it not a violation of encapsulation to not allow a parent's private method to be "overridden" (ie, implemented independently, with the same signature, in a child class)? A parent's private method cannot be accessed or inherited by a child class, in line with principles of encapsulation. It is hidden.
So, why should the child class be restricted from implementing its own method with the same name/signature? Is there a good theoretical foundation for this, or is this just a pragmatic solution of some sort? Do other languages (C++ or C#) have different rules on this?
You can't override a private method, but you can introduce one in a derived class without a problem. This compiles fine:
class Base
{
private void foo()
{
}
}
class Child extends Base
{
private void foo()
{
}
}
Note that if you try to apply the #Override annotation to Child.foo() you'll get a compile-time error. So long as you have your compiler/IDE set to give you warnings or errors if you're missing an #Override annotation, all should be well. Admittedly I prefer the C# approach of override being a keyword, but it was obviously too late to do that in Java.
As for C#'s handling of "overriding" a private method - a private method can't be virtual in the first place, but you can certainly introduce a new private method with the same name as a private method in the base class.
Well, allowing private methods to be overwritten will either cause a leak of encapsulation or a security risk. If we assume that it were possible, then we’d get the following situation:
Let's say that there's a private method boolean hasCredentials() then an extended class could simply override it like this:
boolean hasCredentials() { return true; }
thus breaking the security check.
The only way for the original class to prevent this would be to declare its method final. But now, this is leaks implementation information through the encapsulation, because a derived class now cannot create a method hasCredentials any more – it would clash with the one defined in the base class.
That’s bad: lets say this method doesn’t exist at first in Base. Now, an implementor can legitimately derive a class Derived and give it a method hasCredentials which works as expected.
But now, a new version of the original Base class is released. Its public interface doesn’t change (and neither do its invariants) so we must expect that it doesn’t break existing code. Only it does, because now there’s a name clash with a method in a derived class.
I think the question stems from a misunderstanding:
How is it /not/ a violation of encapsulation to not allow a parent's private method to be "overridden" (ie, implemented independently, with the same signature, in a child class)
The text inside the parentheses is the opposite of the text before it. Java does allow you to “independently implement [a private method], with the same signature, in a child class”. Not allowing this would violate encapsulation, as I’ve explained above.
But “to not allow a parent's private method to be "overridden"” is something different, and necessary to ensure encapsulation.
"Do other languages (C++ or C#) have different rules on this?"
Well, C++ has different rules: the static or dynamic member function binding process and the access privileges enforcements are orthogonal.
Giving a member function the private access privilege modifier means that this function can only be called by its declaring class, not by others (not even the derived classes). When you declare a private member function as virtual, even pure virtual (virtual void foo() = 0;), you allow the base class to benefit from specialization while still enforcing the access privileges.
When it comes to virtual member functions, access privileges tells you what you are supposed to do:
private virtual means that you are allowed to specialize the behavior but the invocation of the member function is made by the base class, surely in a controlled fashion
protected virtual means that you should / must invoke the upper class version of the member function when overriding it
So, in C++, access privilege and virtualness are independent of each other. Determining whether the function is to be statically or dynamically bound is the last step in resolving a function call.
Finally, the Template Method design pattern should be preferred over public virtual member functions.
Reference: Conversations: Virtually Yours
The article gives a practical use of a private virtual member function.
ISO/IEC 14882-2003 §3.4.1
Name lookup may associate more than one declaration with a name if it finds the name to be a function name; the declarations are said to form a set of overloaded functions (13.1). Overload resolution (13.3) takes place after name lookup has succeeded. The access rules (clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded. Only after name lookup, function overload resolution (if applicable) and access checking have succeeded are the attributes introduced by the name’s declaration used further in expression processing (clause 5).
ISO/IEC 14882-2003 §5.2.2
The function called in a member function call is normally selected according to the static type of the object expression (clause 10), but if that function isvirtualand is not specified using aqualified-idthen the function actually called will be the final overrider (10.3) of the selected function in the dynamic type of the object expression [Note: the dynamic type is the type of the object pointed or referred to by the current value of the object expression.
A parent's private method cannot be accessed or inherited by a child class, inline with principles of encapsulation. It is hidden.
So, why should the child class be
restricted from implementing its own
method with the same name/signature?
There is no such restriction. You can do that without any problems, it's just not called "overriding".
Overridden methods are subject to dynamic dispatch, i.e. the method that is actually called is selected at runtime depending on the actual type of the object it's called on. With private method, that does not happen (and should not, as per your first statement). And that's what is meant by the statement "private methods can't be overridden".
I think you're misinterpreting what that post says. It's not saying that the child class is "restricted from implementing its own method with the same name/signature."
Here's the code, slightly edited:
public class PrivateOverride {
private static Test monitor = new Test();
private void f() {
System.out.println("private f()");
}
public static void main(String[] args) {
PrivateOverride po = new Derived();
po.f();
});
}
}
class Derived extends PrivateOverride {
public void f() {
System.out.println("public f()");
}
}
And the quote:
You might reasonably expect the output to be “public f( )”,
The reason for that quote is that the variable po actually holds an instance of Derived. However, since the method is defined as private, the compiler actually looks at the type of the variable, rather than the type of the object. And it translates the method call into invokespecial (I think that's the right opcode, haven't checked JVM spec) rather than invokeinstance.
It seems to be a matter of choice and definition. The reason you can't do this in java is because the specification says so, but the question were more why the specification says so.
The fact that C++ allows this (even if we use virtual keyword to force dynamic dispatch) shows that there is no inherent reason why you couldn't allow this.
However it seem to be perfectly legal to replace the method:
class B {
private int foo()
{
return 42;
}
public int bar()
{
return foo();
}
}
class D extends B {
private int foo()
{
return 43;
}
public int frob()
{
return foo();
}
}
Seems to compile OK (on my compiler), but the D.foo is not related to B.foo (ie it doesn't override it) - bar() always return 42 (by calling B.foo) and frob() always returns 43 (by calling D.foo) no matter whether called on a B or D instance.
One reason that Java does not allow override the method would be that they didn't like to allow the method to be changed as in Konrad Rudolph's example. Note that C++ differs here as you need to use the "virtual" keyword in order to get dynamic dispatch - by default it hasn't so you can't modify code in base class that relies on the hasCredentials method. The above example also protects against this as the D.foo does not replace calls to foo from B.
When the method is private, it's not visible to its child. So there is no meaning of overriding it.
I apologize for using the term override incorrectly and inconsistent with my description. My description describes the scenario. The following code extends Jon Skeet's example to portray my scenario:
class Base {
public void callFoo() {
foo();
}
private void foo() {
}
}
class Child extends Base {
private void foo() {
}
}
Usage is like the following:
Child c = new Child();
c.callFoo();
The issue I experienced is that the parent foo() method was being called even though, as the code shows, I was calling callFoo() on the child instance variable. I thought I was defining a new private method foo() in Child() which the inherited callFoo() method would call, but I think some of what kdgregory has said may apply to my scenario - possibly due to the way the derived class constructor is calling super(), or perhaps not.
There was no compiler warning in Eclipse and the code did compile. The result was unexpected.
Beyond anything said before, there's a very semantic reason for not allowing private methods to be overridden...THEY'RE PRIVATE!!!
If I write a class, and I indicate that a method is 'private', it should be completely unseeable by the outside world. Nobody should be able access it, override it, or anything else. I simply ought to be able to know that it is MY method exclusively and that nobody else is going to muck with it or depend on it. It could not be considered private if someone could muck with it. I believe that it's that simple really.
A class is defined by what methods it makes available and how they behave. Not how those are implemented internally (e.g. via calls to private methods).
Because encapsulation has to do with behavior and not implementation details, private methods have nothing to do with the idea encapsulation. In a sense, your question makes no sense. It's like asking "How is putting cream in coffee not a violation of encapsulation?"
Presumably the private method is used by something that is public. You can override that. In doing so, you've changed behavior.
I mean, obviously, there is no benefit on the polymorphic side,
and declaring (all of) these methods as final would prevent me from overriding them.
And I know IT IS possible to do, and the compiler doesn't prevent you from doing it.
I would love to get a usage example...
There are some marginal cases where such design, if perhaps not optimal, could at least be motivated. For example, you may have a system of classes, all subclasses of a common parent, where each subclass implements a further interface. There may be a set of interfaces with different formalities, but the same essential function.
In that particalar case it wouldn't hurt to make all the methods final and let each subclass add its own methods which make use of them.
I'd say it's part of the "core" component. You build something and you design the architecture, and you know that that method should never be changed.
The abstract class could have package access to some internal methods.
In this case we have
an incomplete class
functionality has to stay the same and grants secured access to the internal model
That is all we need to declare a type abstract and all its methods final. Consider as an example a Panel class that holds the graphics, but not always offers a method to actually make it draw itself - subclasses can have different drawing behaviourse. On the other hand it can offer a final protected DrawBuffer makeCircle() or something like that which, for some reason, has to access the internal model to make a DrawBuffer.
The JIT can take benefit when some methods declared in such way, when it cannot be overridden. (static, private, final, in final class)
let's imagine you have classes:
abstract class A {
public void doSomething() {
// default and only realization;
}
}
class B extends A { ... }
Then you write something like:
A a = MyAFactory.createA();
a.doSomething();
When method cannot be known to be final, and there is possible (even if not loaded just now) overridings, compiler makes second line to invoke virtual method. I.e. first it will determine which exactly class A, then looking in virtual method table, and only then call to particular methods.
But! If method is known as it cannot be overridden, then compiler can place to this point direct call to A.doSomething().
So, it is recommended to make method final unless you need them to be overridden.
Let's imagine class like this:
abstract class C {
public abstract int getMin();
public abstract int getMax();
public final int getSize() {
return getMax() - getMin();
}
}
in this example, it is obvious behavior of getSize() and hardly to imagine when it needs to be changed. So, declaring it final, not only gives a benefit by discarding virtual invocation mechanism, but also protects from unintended override of method with particular and predefined behavior.
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)?
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.
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");
}
}
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(){}
}
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.