From the docs, "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."
I understand the difference between method hiding and overriding. However, it's strange to say that the subclass hides the superclass method because if you have the following:
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public void testInstanceMethod() {
System.out.println("The instance method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
The superclass's static method is called. But by the definition of hiding, the method in the subclass is hiding the one in the superclass. I don't see how the subclass is "covering up/hiding" the superclass static method, as the superclass's method is the one that's actually called.
The superclass's static method is called.
Yes. But that is because you explicitly named the superclass's static method by qualifying with the superclass name in the call statement.
If you had written the main like this instead:
public static void main(String[] args) {
...
testClassMethod();
}
then you would have seen that the Cat version of testClassMethod was called. Here, the Cat.testClassMethod method hides the Animal.testClassMethod method
Cat's testClassMethod() hides Animal.testClassMethod(), since if you didn't have a static testClassMethod() in the Cat class, Cat.testClassMethod() would invoke Animal.testClassMethod().
When you call Animal.testClassMethod(), it's can't be hidden by a sub-class's method.
I think it's called "hiding" because you can no longer access the superclass's method simply by writing the method name. Without the public static void testClassMethod() definition in Cat, your main could say
testClassMethod();
to call the method defined in Animal. But you can no longer do that. Yes, you can still call it by giving it the qualified name:
Animal.testClassMethod();
so it's not completely hidden. But please note that people who write language standards have to come up with names for some concepts that may not quite match the meanings we give words in the non-computing world, so sometimes coming close is the best they can do. You can't try to take the terminology literally. The term hidden has a formal definition somewhere in the JLS, I believe; and that means when you see the term used in the JLS, it means whatever the JLS defines it to mean, neither more nor less.
Consider adding this to your posted example
class Dog extends Animal {
// nothing here
}
Now if you do this:
new Cat().testClassMethod();
new Dog().testClassMethod();
each of the above will give different output. So you could say that the static method in Cat did hide the Animal's static method - while there's no such thing as overriding for static methods, one of the animals printed according to Animal's code and the other did not.
(P.S. I'm definitely not encouraging you to call static methods in this way.)
Related
Ok just for sake knowledge , I tried below cases (Assume that Class A and B are in same package)
ClassA
public class ClassA {
public static void main(String[] args) {
System.out.println("A");
}
}
ClassB
public class ClassB extends ClassA {
public static void main(String[] args) {
System.out.println("B");
}
}
executing above ClassB it will produce output of B now after below change in classB
ClassB
public class ClassB extends ClassA {
//blank body
}
If I compile and run in terminal it gives me output A that was totally surprising as it should had given NoSuchMethodError as no main method was their so kindly explain the weird behavior ?
Note: Many answers contains Override word please use hiding as we cannot override static methods in java.
In the first case, you're hiding the main method since you're defining a new one in the subclass, in the second case you didn't you'll inherent A's main.
See The Java™ Tutorials - Overriding and Hiding:
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.
In Java subclasses inherit all methods of their base classes, including their static methods.
Defining an instance method in the subclass with the matching name and parameters of a method in the superclass is an override. Doing the same thing for static methods hides the method of the superclass.
Hiding does not mean that the method disappears, though: both methods remain callable with the appropriate syntax. In your first example everything is clear: both A and B have their own main; calling A.main() prints A, while calling B.main() prints B.
In your second example, calling B.main() is also allowed. Since main is inherited from A, the result is printing A.
public static void main(String[] args) is just a method which you inherit from A in second case.
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.
I searched a lot. The difference between them is that override is for the instance method and hidden is for the static method. And the hidden is in fact the redefinition of the method. But I still don't get it.If redefinition means that the static method of parent still exists in the subclass, it is just we can't see it? Or why we call it hidden but not any other words? But if it exists, I can't find a way to call the method again. To be honest from a function level I can't find why they are different. Can some one explain it from a deeper level such as memory?
Static members(methods and variables) will not be present in the sub class(Child class) object which inherit them but they'll be present as a single copy in the memory.
Static members can be accessed by the class name of both Super class and sub class but they are not physically present in the object of these classes.
Where as when you inherit non-static members, Sub class object in memory will contain both inherited methods as well as the methods of its own. So when you try to write a similar method here, super class method will be overridden. On the other hand as static methods does not participate in inheritance, any similar method you write that is present in super class, new method will run every-time it is asked for. Parent class method is just hidden but not overridden!
From JLS 8.4.8.2, example 8.4.8.2-1 shows us that a hidden method binds to the type of the reference (Super), while an overriden method binds to the type of Object (Sub).
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
Output:
Goodnight, Dick
If you call Superclass.staticMethod() you will get the method as defined on the superclass, regardless of any hiding taking place in subclasses. On the other hand, if you call ((Superclass)subObj).instanceMethod() you'll still be calling the method as it is overridden in the subclass.
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
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.