当一个类扩展另一个类时,它继承了超类的所有方法和变量。如果在具有相同签名的子类中以不同方式定义方法和变量,则可以在子类中以不同方式使用它们。 现在Oracle区分了覆盖和隐藏(http://docs.oracle.com/javase/tutorial/java/IandI/override.html)。 它表示实例方法会覆盖其超类的方法,而类方法会隐藏它。 “隐藏和覆盖之间的区别具有重要意义。被调用的被重写方法的版本是子类中的一个。被调用的隐藏方法的版本取决于它是从超类还是从子类调用的。”
假设我有2个课程是和可能。是延伸可能。 也许有String a。
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
我说:它会打印出来 也许 是 也许 是
但是在我阅读了Oracle文章后,我认为它必须打印出来:
yes
yes
maybe
yes
因为实例方法会覆盖其超类方法。
我很确定我对输出是正确的,但我确信,Oracle也知道 更好,所以我想我只是不明白这篇文章。 当我从超类的对象调用实例方法时,它使用覆盖的方法是不正确的。 所以我不明白为什么要区分覆盖和隐藏! 有人可以帮忙吗?
编辑;插入代码而不是描述类!
答案 0 :(得分:5)
根本无法覆盖静态方法。它们不是多态的,因为它们不作用于类的实例,而是作用于类本身。
如果您致电Maybe.printOut()
,则会调用printOut()
中定义的静态Maybe
方法。 printOut()
中定义的方法Yes
这一事实无关紧要:除了名称之外,这两种方法没有任何共同之处。
请注意,您只需编写程序并执行即可确认或确认您的疑虑。
隐藏方法的问题仅在您开始在对象的实例上调用静态方法时发生。这是非常糟糕的做法,永远不应该这样做。如果您不遵守此规则,请执行以下操作:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
结果将是maybe maybe
,因为在静态方法的情况下,重要的是不对象的具体类型(Maybe
和Yes
),但他们的声明类型(Maybe
和Maybe
)。
答案 1 :(得分:1)
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT将是: - (静态方法与实例方法)
点 C C SP SC 属
答案 2 :(得分:0)
根据您的示例采用以下示例:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
每个派生类都会覆盖对overwritten
的调用。因此每个方法都将使用属于当前对象的实现。另一方面,对hidden
的调用将始终使用定义类的实现。因此,Maybe.called
始终会调用Maybe.hidden
,而永远不调用Yes.hidden
。要致电Yes.hidden
,您必须在Yes
内的方法中使用,或使用限定名称。
用不同的词语表达:
hidden()
方法中的inherited()
调用) (即在其任何方法的主体中,或者在使用此类的名称限定时)现在将调用一个完全不同的函数,需要一个资格来从父类访问同名的静态方法。也许您的困惑来自于您假设覆盖以影响对该方法的所有调用,即使对于基类的对象也是如此。