首页 > 解决方案 > java中方法隐藏概念中“隐藏”一词的含义是什么?

问题描述

这个问题已经提出来讨论与java中的静态方法相关的术语隐藏。每当在父类和子类中定义了具有相同签名的静态方法时,就说子类方法隐藏了父类中的方法。我的问题是关于隐藏的使用,因为我们知道静态方法将通过类名访问,或者如果我们尝试创建引用(这是一种不好的做法),方法将基于引用类型被调用。那么隐藏是如何出现的,以下面的代码为例:

public class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod(); // prints The static method in Animal
    }
}

有人可以解释一下子方法如何在这里隐藏父方法吗?(使用父引用调用父方法,那么隐藏是如何出现的)

标签: javastatic-methodsmethod-hiding

解决方案


子方法是怎么把父方法隐藏在这里的?

正如您所说,通过定义具有相同签名的静态方法。

隐藏是如何进入画面的?

Cat.testClassMethod();

有些人可能期望在这里调用父方法(通过类比多态)。但是通过类方法隐藏的想法是不同的:

如果类 C 声明或继承静态方法 m,则称 m 隐藏任何方法 m',其中 m 的签名是 m' 签名的子签名(第 8.4.2 节),位于C 中的代码可以访问(第 6.6 节)的 C
。...
可以通过使用限定名称或使用包含关键字 super 或强制转换为 a 的方法调用表达式(第 15.12 节)来访问隐藏方法超类类型。
...

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());  // Goodnight, Dick
    }
}

JLS 10 - 8.4.8.2。隐藏(通过类方法)

这个例子完美地展示了覆盖和隐藏之间的区别。同时,这是一个不好的实践演示——在实例上调用静态方法。

我将尝试通过提供另一个示例来说明这一点。

由于继承了公共静态方法,因此以下代码段

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

class Cat extends Animal {
    public static void main(String[] args) {
        // Cat: I don't have own method, probably I inherited it from the parent.
        //      O, yes. I can call it. 
        Cat.testClassMethod();
    }
}

印刷

The static method in Animal

现在我们要添加testClassMethodCat.

class Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Animal");
    }
}

class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The static method in Cat");
    }

    public static void main(String[] args) {
        // Cat: I have two version of the method: mine and the inherited one.
        //      The caller specified my class name, so he wanted my version. 
        //      I will call my method hiding the parent method.
        Cat.testClassMethod();

        // If he wanted Animal's version, he would write
        Animal.testClassMethod();

        // or (DON'T DO THIS)
        ((Animal)new Cat()).testClassMethod();
    }
}

推荐阅读