Strange case of static method override in java - java

It is written everywhere that static method cannot be overriden, but when I try to reduce the access specifier say from public to protected it gives an error. for example
public class StaticOverrideFunda {
public static void foo(){
System.out.println("Parent Foo");
}
}
public class B extends StaticOverrideFunda{
protected static void foo(){
System.out.println("Child Foo");
}
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
B.foo();
}
}
It says
Cannot reduce the visibility of the inherited method
So insense it is following the overriding rules, how come we are saying foo is not being overridden in B class? Why do we say it is hiding/shadowing and not overriding?

It's following some of the same rules as overriding, but that doesn't mean it is overriding. In this case, it's the rules in section 8.4.8.3 of the JLS, "Requirements in Overriding and Hiding":
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: [...]
It's still not overriding, as the method wouldn't be invoked polymorphically - you can't write a call which will sometimes end up calling StaticOverrideFunda.foo and sometimes end up calling B.foo; the target is determined entirely at compile time.
It would be worth reviewing the rest of section 8.4.8, which defines overriding as being something which occurs on instance methods.

You yourself posted answer in your question, overriding means having different code in child class for same method. As static methods cannot be overridden you cannot play with the visibility by modifying access specifiers.

Related

What is the purpose of protected modifier for static methods

I found such an usage of protected modifier while searching for a solution for my other question: Ignoring case in strings with unitils ReflectionComparator
In the org.unitils.reflectionassert.ReflectionComparatorFactory class there is a method with the signature:
protected static List<Comparator> getComparatorChain(Set<ReflectionComparatorMode> modes)
But this is only a particular case.
After all we can always extend such any non-final class and "override" it's static protected method with the new public modifier. Say, we have a class A:
public class A {
protected static void test() {
// do some stuff
}
}
and want to use it in another package:
public class UseA {
private static class MyA extends A {
public static void test() {
A.test();
}
}
void useA() {
// A.test(); compile error, sure
MyA.test();
}
}
I concentrate my question on a general situation when some static method was declared as protected. I'm not asking about non-static fields or methods, because in some cases class can have a private constructor or a very complicated constructor with lots special params. But what is the purpose of such "hiding" static methods if entire class isn't final? Is such usage an OOP mistake or just a very weak "protection"?
But what is the purpose of such "hiding" static methods if entire class isn't final?
A protected static method would allow you to provide "utility" type functionality to derived classes, without exposing them in the public API where they might not make sense on their own.
I don't know the implementation of the getComparatorChain method you reference, but I imagine it's such a method. It would be marked static if it's not tied to any specific instance, and marked protected so as not to be a part of the public API, but also to allow derived classes to re-use the utility method in it's own implementation.
Overriding a static method reference means hiding it's implementation. See: Java Documentation's Overriding and Hiding Methods
Static Methods
If a subclass defines a static method with the same signature as a static method in the superclass, then the method in the subclass hides the one in the superclass.
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.

private method of superclass executes on subclass reference

Given the following code:
SuperClass :
package poc.poc;
public class SuperClass {
private void method() {
System.out.println("SuperClass!");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
SuperClass s = new SubClass();
s.method();
}
}
SubClass :
package poc.poc;
public class SubClass extends SuperClass {
public void method() {
System.out.println("Subclass!");
}
}
When I run the main method of SuperClass , I would expect to get an exception of some sort, but actually the code in the SuperClass is run, rather than the code in the SubClass, and therefore running an instance method of the superclass type on a subclass instance.
Why does this happen?
EDIT: Doesn't this violate encapsulation?
P.S. When changing to protected rather than private modifier, polymorphism starts to kick in and we're back to something I would call "expected behavior"
There is no way to override a private method. Instead, the subclass is hiding it. That means that when the subclass is used polymorphically, the method is not considered one of the parent's existing methods. It's like a whole new method that's not available through polymorphism.
The private method is not part of the parent's class contract. Polymorphism only applies to methods that are part of the parent's contract. If it wasn't like that, you could cause a class to act differently than its contract, by changing implementation where the author wanted it to be private. If the author wanted you to do that, they would have used protected instead. In effect, a private method is like final.
In this particular main method, because it is defined in the actual parent's class, it is able to see a private method and therefore able to call it. If your main method has been in any other class and tried to call it, it would have failed.
A private method cannot be overrided, that alone explains what you see here. You are able to call the method in your main because the main is in the same class, otherwise it would not be possible.
You correctly analyzed what happens when changing private to protected : the method is now overridable and the "nearest" definition of it is executed when calling it on a subclass instance.

Inheriting static methods in Java?

So I know that in Java when you have a static method you are supposed to call it with the format ClassName.method() rather than use the same structure as you would for instance methods, namely:
ClassName myObject = new ClassName();
myObject.method();
However, if you were to do it this way it would still be valid code and would work. Let's say I decide to do this where the method in question is static, and have the following setup:
public SuperClass {
public static int foo(int x) {
return x;
}
}
public SubClass extends SuperClass {
public static int foo(int x) { // Overriding foo() in SuperClass
return x + 1;
}
}
public MyDriver {
public static void main(String[] args) {
SuperClass myObject = new SubClass(); // Upcasting.
System.out.println(myObject.foo(5)); // This should polymorphically print 6
}
}
What prints out on the screen, however, is 5 rather than 6. Why?
Static methods apply only to the class they are defined in, and they cannot be overridden.
When you call myObject.foo(5), you are calling SuperClass.foo(5) in reality, because you declared myObject as a SuperClass, regardless of whether you instantiated it as one.
The proper way to call a static method is to call it directly from the class it is declared in, so if you wanted to call SubClass.foo(), you must call it from an explicitly declared SubClass instance (meaning no upcasting), or you need to call SubClass.foo() like so.
The simple answer is that calling static methods from instances evaluates to calling those same methods from the declared type with no instance rather than the instance type.
I am not certain of this, but I would not be surprised if when the code is compiled into byte-code, that the instance static method call would actually be compiled into a direct call to the declared type.
Edit: An upvote brought my attention back to this and I cleaned up the explanation to make it more clear and fix some negligible grammatical mistakes on my part. I hope this helps future readers.
Using instances of a class to call that class's static methods is something you should avoid, since it can cause confusion. If you need to call any method polymorphically, make it an instance method. You cannot polymorphically call a static method. The reason the SuperClass invocation is called is because that is the apparent class of myObject at compile-time. This effect can also be seen in the following scenario:
public void doSomething(SuperClass param) {
System.out.println("SuperClass");
}
public void doSomething(SubClass param) {
System.out.println("SubClass");
}
public void test() {
SuperClass myObject = new SubClass();
doSomething(myObject);
}
If test() is called, SuperClass will be printed.
Static methods don't depends on the instance, they belong to the class and only to the class, in fact if you have a static method you'll always access to one unique instance always.
myObject.foo(5)
is only a shortcut, what you really are doing is
SuperClass.foo(5)
Static methods are treated as global by the JVM, they are not bound to an object instance at all. By the way, you can only overload static methods, but you can not override. So check for "Oracle Documentation for Overriding and Hiding Documents".
Defining a Method with the Same Signature as a Superclass's Method:
-----------------------------------------Superclass Instance MethodSuperclass Static Method
Subclass Instance Method Overrides Generates a compile-time error
Subclass Static Method Generates a compile-time error Hides

Why am I getting method overriding error?

THis is my superclass:
class Superclass {
int a=89;
final static void m( int p){
System.out.println("Inside superclass");
}
static void n(){
system.out.print("superclass");
}
}
This is my subclass::
class Subclass extends Superclass {
int a=90;
static void m( int p){
System.out.println("Inside subclass");
}
static void n(){
system.out.print("subclass");
}
}
Main class:
class main {
public static void main(String[] args) {
Subclass.m(89);
new Subclass().n();
}
}
the problem is that i cannot understand why Javac is giving me overriding error in static method..an P.S plzz elaborate that all rules for overriding are also valid for hiding. like
The new method definition must have the same method signature (i.e.,
method name and parameters) and the same return type. Whether
parameters in the overriding method should be final is at the
discretion of the subclass method's signature does not encompass the
final modifier of parameters, only their types and order.
The new
method definition cannot narrow the accessibility of the method, but
it can widen it The new method definition can only specify all or
none, or a subset of the exception classes (including their
subclasses) specified in the throws clause of the overridden method in
the superclass
my error is:
run:
Exception in thread "main" java.lang.RuntimeException: Uncompilable
source code - m(int) in javaapplication3.Subclass cannot override
m(int) in javaapplication3.Superclass overridden method is
static,final at javaapplication3.Subclass.m(JavaApplication3.java:18)
at javaapplication3.min.main(JavaApplication3.java:25) Java Result: 1
also i want to ask if static members called from classname to resolve whicch version of method is executed when method is hidden by subclass extending the superclass
what if i make anonymous object and then call method then how the compiler determines which version of method should be called.
in above code in main class i type this: new Subclass().n();
how does the compiler know subclass version of method should be called even if i am not providing the type of reference variable
From the JLS 8.4.3.3:
A method can be declared final to prevent subclasses from overriding or hiding it.
Static methods with the same signature from the parent class are hidden when called from an instance of the subclass. However, you can't override/hide final methods.
The keyword final will disable the method from being hidden. So they cannot be hidden and an attempt to do so will result in a compiler error. There is a nice explanation on this on Javaranch.
What you are observing here is in accordance with JLS 8.4.3.3 which states that:
It is a compile-time error to attempt to override or hide a final
method.
You are trying to override final static void m method in subclass , which is not permitted by Java compiler.

why should we widen the accessibility of overridden methods?

why should we widen the accessibility of overridden methods ? If the super class has a protected method and subclass has same method with public. Why should happen?
It's a different method! Subclasses don't inherit private methods! So you're not "overriding" at all. You are simply DEFINING a method with the same name as the private method in the superclass.
class A
{
private void myMethod() { }
}
class B extends A
{
public void myMethod() { } // a completely different method. Has nothing to do with the above method. It is not an override.
}
Because in an object hierarchy, JVM will always run the Overriden method. If your overriden method is not accessible, then it is useless.
public class A{
void A(){}
}
public class B extends A{
private void A(){} //this makes no sence and its impossible
PSV main(String ..){
A a = new B();
a.A(); //error as JVM cannot call overriden method which is private.
}
}
Methods declared as private or static can not be overridden!
Annotation #Override indicates that a method declaration is intended to override a method declaration in a superclass. If a method is annotated with this annotation type but does not override a superclass method, compilers are required to generate an error message.
Use it every time you override a method for two benefits. This way, if you make a common mistake of misspelling a method name or not correctly matching the parameters, you will be warned that you method does not actually override as you think it does. Secondly, it makes your code easier to understand because it is more obvious when methods are overwritten.
And in Java 1.6 you can use it to mark when a method implements an interface for the same benefits.

Categories