Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do these two code samples produce different outputs?

Tags:

java

static

Sample 1:

 class Animal {
     public static void saySomething() { System.out.print(" Gurrr!"); 
   }
 }
 class Cow extends Animal {
    public static void saySomething() { 
     System.out.print(" Moo!"); 
    }
    public static void main(String [] args) {
         Animal [] animals = {new Animal(), new Cow()};
         for( Animal a : animals) {
           a.saySomething();
         }
         new Cow().saySomething();
    }
 }

Output is:

 Gurrr! Gurrr! Moo!

Sample 2:

 class Animal {
     public void saySomething() { System.out.print(" Gurrr!"); 
   }
 }
 class Cow extends Animal {
    public void saySomething() { 
     System.out.print(" Moo!"); 
    }
    public static void main(String [] args) {
         Animal [] animals = {new Animal(), new Cow()};
         for( Animal a : animals) {
           a.saySomething();
         }
         new Cow().saySomething();
    }
 }

Output:

 Gurrr! Moo! Moo!

I just don't understand why making saySomething non-static causes the second call to saySomething invoke the Cow version instead of the Animal version. My understanding was that Gurrr! Moo! Moo! would be the output in either case.

like image 287
Bad Request Avatar asked Sep 09 '10 19:09

Bad Request


2 Answers

When you call saySomething() on an animal, the actual type of the animal doesn't count because saySomething() is static.

Animal cow = new Cow();
cow.saySomething(); 

is the same as

Animal.saySomething();

A JLS example :

When a target reference is computed and then discarded because the invocation mode is static, the reference is not examined to see whether it is null:

class Test {
  static void mountain() {
      System.out.println("Monadnock");
  }
  static Test favorite(){
       System.out.print("Mount ");
       return null;
   }
   public static void main(String[] args) {
       favorite().mountain();
   }

}

which prints:
Mount Monadnock
Here favorite returns null, yet no NullPointerException is thrown.


Resources :

  • JLS - Is the Chosen Method Appropriate?

On the same topic :

  • Java Static confusion
like image 160
Colin Hebert Avatar answered Sep 19 '22 20:09

Colin Hebert


You cannot override static methods with the same signature in subclasses, just hide them.

For class methods, the runtime system invokes the method defined in the compile-time type of the reference on which the method is called. For instance methods, the runtime system invokes the method defined in the runtime type of the reference on which the method is called.

http://life.csu.edu.au/java-tut/java/javaOO/override.html

like image 32
miku Avatar answered Sep 21 '22 20:09

miku