这个词的意义是什么?隐藏"在java中隐藏概念的方法?

时间:2018-04-28 08:10:33

标签: java static-methods method-hiding

已经提出了一个问题来讨论与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
    }
}

有人可以解释子方法如何隐藏父方法吗? (使用父引用调用父方法,因此隐藏如何进入图片)

4 个答案:

答案 0 :(得分:1)

  

子方法如何隐藏父方法?

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

  

隐藏如何进入图片?

Cat.testClassMethod();

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

  

如果C类声明或继承静态方法m,则m被称为隐藏任何方法m',其中m的签名是m'中签名的子签名(第8.4.2节),在超类中和C的超接口,否则可以访问(§6.6)到C中的代码   ...
  可以使用限定名称或使用包含关键字super或强制转换为超类类型的方法调用表达式(第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. Hiding (by Class Methods)

此示例非常适合显示覆盖和隐藏之间的区别。同时,这是一个不好的练习演示 - 在实例上调用静态方法。

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

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

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

现在我们要将testClassMethod添加到Cat

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();
    }
}

答案 1 :(得分:1)

这充分说明了为什么打算隐藏静态方法是不好的做法。在编译时静态选择该方法,而不考虑实际的实例类型。

我认为带回家的短语应该是"隐藏不是凌驾...... 而不是" ,意味着Java甚至不会查看对象/实例(仅查看声明的类型):

Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testClassMethod(); //bad to do, but you can see it uses the declared "Animal" class

Cat.testClassMethod(); //Uses method in Cat
myCat.testClassMethod(); //Uses method in Cat

((Animal) null).testClassMethod(); //Uses Animal method, doesn't look at instance
((Cat) null).testClassMethod(); //Uses Cat method, doesn't look at instance

现在有趣的部分:如果您从Cat 中删除该方法该怎么办? 所有这些调用仍然可以使用Animal方法,这意味着:

  • 隐藏静态方法
  • 是一种非常糟糕的做法
  • 使用类实例调用静态方法同样不好,因为在隐藏方法的情况下,它很容易被误导......

回答问题:隐藏用Cat.testClassMethod()myCat.testClassMethod()来说明,它根据声明的类型调用静态方法。如果testClassMethod()中没有Cat,则Java会调用父级。

答案 2 :(得分:0)

所有final,static和private方法和变量都使用静态绑定,并由编译器绑定。静态绑定使用Type信息进行绑定(在本例中为Animal)。

因此,在您的情况下,myAnimal.testClassMethod();将在Animal中打印静态方法,因为声明的类型为Animal

答案 3 :(得分:0)

静态方法不参与动态绑定(多态)。

静态方法不会被覆盖,静态方法会被子类隐藏。

致电Cat.testClassMethod()的人可能会期待Animal.testClassMethod()

的行为

因此Cat.testClassMethod()隐藏了Animal.testClassMethod()