已经提出了一个问题来讨论与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
}
}
有人可以解释子方法如何隐藏父方法吗? (使用父引用调用父方法,因此隐藏如何进入图片)
答案 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 } }
此示例非常适合显示覆盖和隐藏之间的区别。同时,这是一个不好的练习演示 - 在实例上调用静态方法。
我将通过提供另一个例子来说明这一点。
由于继承了公共静态方法,因此以下代码段
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()