Are there any legitimate reasons to hide static methods? [duplicate] - java

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Why doesn't Java allow overriding of static methods?
Is there any legitimate reason why one would want a derived class to override hide a static method of the base class?

Terminology aside, static methods in Java do have a kind of overriding relation, implied by binary compatibility section 13.4.12. If T extends S, S declared m(), T.m() can refer to a method in T or S, depending on if m() is declared in T; and it's ok to add or remove m() from T, without breaking any code calling T.m(). (This implies JVM invokestatic instruction does a sort of dynamic method lookup up the super class chain)
However, this is nothing but trouble. It is really dangerous if the meaning of T.m() silently changes because now it's pointing to a different method. (Instance methods shall inherit contracts so that's not a problem; there's no such understanding in static methods.)
So this "feature" should never be used; the language shouldn't have enabled it to begin with.
The good practice: If we call T.m(), m() must be declared in T; and it should never be removed from T without removing all T.m() first.

Static methods cannot be overriden
In order to override a method, the method must first be inherited. If the method is not inherited there is no chance for overriding. Therefore, you can never override a private method as they are not inherited.

Related

Overriding, redeclaring, hiding and redefining of methods in classes, interfaces and classes implementing interfaces [duplicate]

This question already has answers here:
Can I override and overload static methods in Java?
(19 answers)
Closed 5 months ago.
Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method in the class extending class case), and any other method can only be overridden there? And is redefining the same as overriding?
If not, can someone please explain these concepts with a flowchart (I've looked at other explanations and they don't give me the overview I'm looking for)?
Would it be correct to say that static methods in a class extended
No. static methods fundamentally are un-inheritable, and un-overridable. Or rather, conceptually it just doesn't apply.
Saying: "This static method is an override" is a bit like stating: "This smells blue" - it's not clear what that would even mean.
overriding is relevant essentially only for the notion of dynamic dispatch. Dynamic dispatch is this idea:
class Dog {
void bark() { System.out.println("Woof"); }
}
class Bulldog extends Dog {
void bark() { System.out.println("Grrrr"); }
}
Dog d = new Bulldog();
d.bark(); // prints "Grrrr"
That's dynamic dispatch at work. d is a variable. Like all non-primitives in java, it is a reference. Meaning, values stored in this variable are the reference - a pointer. An address in an addressbook that lets you get to a house, not the house itself. d's type is Dog. Its value is a reference to an actual instance of some object (and java guarantees that whatever the actual type it is an instance of, that type is Dog or a subtype of Dog). That reference gets you an instance of Bulldog. So, when invoking bark() here, what happens?
Dynamic dispatch: Java finds the most specific implementation of this method, and calls that. So that prints Grrrr, and not Woof.
However, when talking about static methods, the entire concept doesn't apply. Dynamic dispatch occurs because there is a discrepancy between the type of the reference (which is Dog here, that's the type of variable d) and the type of the thing the reference is pointing at (which is Bulldog). Overriding as a concept exists because these 2 types may not be the same.
When invoking static methods, this doesn't come up. You always write SomeType.someStaticMethod(), so what would dynamic dispatch even be?
SIDENOTE: You can legally invoke static methods using an expression. This is legal:
List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works
But make no mistake - the compiler treats it the same and cares only about the type of list, not about the object the variable is pointing at. In fact, list = null; list.of("a", "b"); works fine, no NullPointerException, proving the point that list doesn't get dereferenced when you do this. All style guides strongly recommend not doing this, for good reason.
SIDENOTE 2: Unfortunately java lets you declare a static method as final which is weird: final means: Cannot be overridden, and we just figured out that 'override' conceptually doesn't make sense for static methods. It's just what it is - it's a design error in the original java spec and java does not like making changes that break existing code unless there is an incredibly good reason to do so, and whilst this spec brainfart is annoying, it doesn't hurt much. Just don't declare your static methods final. It even adds a rule (subtypes cannot declare a static method with the same signature) which is even more bizarre. Again, disregard that - java spec error that doesn't get fixed because not worth the headache.
And is redefining the same as overriding?
Yes. 2 words for the same thing. The correct term is 'override' - both the java lang spec uses this term, and the vast majority of the community does. If I was an editor of whatever tutorial, blogpost, documentation, or presentation you got this 'redefine' term from, I'd edit it. Unless the author was specifically talking about this:
class Parent {
static void foo() {}
}
class Child extends Parent {
static void foo() {}
}
In which case 'override' is the wrong term to use (given that static methods and override are orthogonal concepts), though I wouldn't use 'redefine' either. You're just defining a method named foo in one class, and also defining a method named foo in another. The fact that one is a child of the other is irrelevant; both have a foo method now. The foo method in child does not override or redefine anything; there's no such thing in static world.
with a flowchart
A flowchart requires some sort of flow to chart. Hence the name. No such thing here.

Can overloading and overriding in java be static polymorphism as well as dynamic polymorphism?

Well this type of questions have been answered already but this confused me. I have spent lot of time going through lots of answer so please go through my question before making it duplicate.
case 1 -
static polymorphism - function overloading
dynamic polymorphism - function overriding
links -
https://stackoverflow.com/a/12894211/3181738
https://stackoverflow.com/a/20783390/3181738
and many others.
My confusion is that in all the examples dynamic polymorphism is shown using upcasting. What if I don't upcast.
class A{
public void show(){
System.out.print("A");
}
}
class B extends A{
public void show(){
System.out.print("B");
}
public static void main(String[] s){
A a = new B();
a.show(); // upcasting. It is dynamic polymorphism.
B b = new B();
b.show(); // Now java compiler can decide so is it still dynamic polymorphism?
}
}
case 2 -
static polymorphism is achieved via overloading if method is private , static or final.
So what about overloading of public and default methods?
Static methods can only be overloaded.
Non-static methods can be both overridden and overloaded.
public/protected/private doesn't affect this directly, except that since private methods can't be seen from subclasses, they can't be overridden either. The exact rules are defined here
And if you want to prevent the override of a non-static method, you can declare it final. (private methods are therefore implicitly final.)
Q1 upcasting: Upcasting and treating a subclass object as if it were a parent class object is the essence of polymorphism. So your question, "What if I don't upcast?" Then you are not using polymorphism
Q2 static polymorphism - method overridding: This is what it's saying:
static: static methods are overwritable, since they are associated with the class, not the object. So for instance, if you have a class with a main method, and then you subclass that, and add a main method to the subclass, when you execute the main method in the subclass, it is statically overridden
private: private methods are not inherited and cannot be called in the subclass, unless that are statically overridden
final: final methods are not overriddable. Therefore, redefining them in a subclass creates a statically overridden method
Case 1
At compile time, the compiler will identify the method signature that matches ie. it will be show() with no parameters in your example. Whether it is A's or B's method that gets invoked though is still runtime even though in your example you are sure it is a B.
Case 2
I think that the visibility rules of methods maybe causing some confusion for you.
The decision of which overloaded method that will be called at runtime will be decided at compile time ie. overloaded method is statically decided - this is regardless of whether it is public, package-private (default), or private. If the object, in which the method call occurs, does not have visibility of the method it fails at compile time.
As others have said - overriding does not apply to static methods since it is part of the class not the instance.

Reducing the visibility of a static method

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.

JVM - Order of execution of sub class methods and the use of #override [duplicate]

This question already has answers here:
When do you use Java's #Override annotation and why?
(27 answers)
Closed 9 years ago.
This is a newbie question.
I read that JVM's execution starts from searching for the methodname from lowest class in the hierarchy and if the method is not available in that class it traverses to the parent class looking for the method.
If this is the case then why do we need to use "#override" for adding custom logic to the inherited class ?
The below example illustrates my question
class superclassA
{
method()
{
}
}
class subclassB extends superclassA
{
#Override
//While executing if JVM starts looking for the method name from the lowest hierarchy
//then why do we have to use "override" as the methodname will be matched from the lowest level itself?
method()
{
--custom subclass specific code...
}
}
If this is the case then why do we need to use "#override" for adding custom logic to the inherited class?
We don't. The #Override annotation has no technical meaning - it exists to document the fact that this method overrides one in the superclass, which has some advantages:
If you look at the code, it tells you there is an superclass method that might be important to understand what this method does
You will get a compiler error if the superclass method's signature changes in a way that the subclass method does in fact not override it anymore.
You can get a compiler warning if you override a method without using the annotation, in case you do it inadvertantly.
#Override simply helps Java compiler detect errors in source code, compilers are generate an error if a method annotated with #Override does not override it in fact.
It is not mandatory to annotate a method that overrides a supertype methods with #Override.
You don't need #Override. But it's a useful annotation that causes the compiler to check whether or not you are really overriding the method that you say you are. When you #Override a method that is not actually overriding a method, the compiler will inform you of this discrepancy. Additionally, it just makes your code more clear: since all methods in Java are implicitly virtual, and a method in a derived class with the same signature as that of a non-final method in a super class implicitly overrides it1, adding #Override makes the code easier for humans to understand.
1: To be clear, you can not have a method in a derived class with the same signature as a final method in a super class.

java basics about final keyword

Can final keyword be used for a method?
Absolutely! The final keyword can be applied to just about anything, in each case meaning "you don't get to change this anymore."
Here's what it means when applied to...
a variable: You simply cannot assign the variable a new value (rendering it a constant, of course)
a method: You cannot re-implement (i.e., override) this method in a subclass
a class: You cannot define a subclass
In each case we're simply indicating: once this thing is declared, this is the last value (or implementation) you'll ever see for it.
Yes, it is possible to declare a method as final. That will mean that a method cannot be overridden by its subclasses.
From The Java Language Specifications, Third Edition, Section 8.4.3.3:
A method can be declared final to
prevent subclasses from overriding or
hiding it. It is a compile-time error
to attempt to override or hide a final
method.
For more information, the Writing Final Classes and Methods page from The Java Tutorials has more information.
Yes.
You can make a method final
public class A {
public static final void f() {
System.out.println("test");
}
}
There are typically two reasons for making a method final
When a method is final, it "may" be inlined.
When a method is final, the method is impossible to override.
Sure can. Making it impossible to override.
Sure, check out The Final Word on the Final Keyword
public abstract class AbstractBase
{
public final void performOperation() // cannot be overridden
{
prepareForOperation();
doPerformOperation();
}
protected abstract void doPerformOperation(); // must override
}
Yes.
A final method cannot be overridden by subclasses. This is often used to prevent subclasses from altering crucial behaviors of the class.
As a note to the other answers. You can use final. In practice I rarely see people using it and I'm not sure why.
A lot of the code I write these days is intended for multi-threaded environments and I tend to make the class final an immutable (if its a value class) so that it is threadsafe.
The problem with marking some methods as final (and not others) is that you are stating that there is something special about that method and nothing special about the others. That's rarely what people actually mean in my experience.
If a class is intended for inheritence you need to keep it clean and keep it small to prevent unwanted side-effects. All this depends on whether you are writing code for your self and your team or whether you are writing for a wider audience - i.e. a public api on an Open Source project or a commercial project.
yes, final keyword can be used for a method. It will preserve the immutability. it prevents between methods from being broken. For example, suppose the implementation of some method of class X assumes that method M will behave in a certain way. Declaring X or M as final will prevent derived classes from redefining M in such a way as to cause X to behave incorrectly.

Categories

Resources