Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么这两个代码示例产生不同的输出?_Java_Static - Fatal编程技术网

Java 为什么这两个代码示例产生不同的输出?

Java 为什么这两个代码示例产生不同的输出?,java,static,Java,Static,样本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

样本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();
    }
 }
输出为:

 Gurrr! Gurrr! Moo!
样本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();
    }
 }
输出:

 Gurrr! Moo! Moo!

我只是不明白为什么让saySomething非静态会导致第二次调用saySomething调用的是奶牛版本而不是动物版本。我的理解是,
gurr!哞!呜呜都将是输出。

在动物上调用
saySomething()
时,动物的实际类型不计算,因为
saySomething()
是静态的

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

Animal.saySomething();

JLS示例:

当由于调用模式是静态的而计算并丢弃目标引用时,不会检查该引用是否为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();
   }
}

哪个打印:
蒙纳多克山
此处favorite返回null,但未引发NullPointerException


资源:

关于同一主题:

您不能覆盖子类中具有相同签名的静态方法,只需隐藏它们即可

对于类方法,运行时系统调用调用该方法的引用的编译时类型中定义的方法。例如方法,运行时系统调用调用方法的引用的运行时类型中定义的方法


一些已知的压倒一切的“陷阱”

  • 不能重写静态方法
  • 无法重写私有方法

这解释了输出。

静态方法绑定到对象的“类”,而不是“实例”。
因为您指的是“动物”并调用静态方法saySomething()。除非您指的是Cow,否则它将始终调用“Animal”。

静态方法在编译时绑定到它们的类,不能以多态方式使用。当您在Animal上声明一个“静态”方法时,它将永远绑定到Animal类,并且不能被重写。静态方法绑定到类对象,而不是类的实例

常规方法在运行时绑定,因此JVM可以查看您对“saySomething”的调用,并尝试确定您是否正在传递Animal的子类,如果是,它是否覆盖了
saySomething()
方法。常规方法绑定到对象的实例,而不是类本身

这也是为什么你永远无法做到这一点:

class Animal
{
   public abstract static void saySomething();
}

因为“static”意味着“在编译时绑定”,所以静态和抽象的东西是没有意义的。

我一直不明白为什么Java允许通过对象引用调用静态方法。这是没有必要的,它会导致像这样的混乱。同意。C++也让你做了。我猜这只会让编译器编写者更容易允许这种访问。我在这里试图为这一点辩护:“Java语言规范这么说”就是它的全部内容。首先,为什么允许您从这样的实例引用调用静态方法,这才是真正的奇怪之处。但至少已经有一个庞大的社区维基帖子在上面:)