java中的以下代码,当在elipse上运行时,即使我们替换
也会提供相同的输出superclass s=new sub();
用,
sub s= new sub();
请注意,我们已经覆盖了方法。
输出是:
changed supermethod in sub class
num is sub class 5
代码:
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
void supermethod(){
System.out.println("supermethod as in superclass");
}
void method(){
System.out.println("num in superclass "+num);
}
}
class sub extends superclass{
int num=5;
void method(){
System.out.println("num is sub class "+num);
}
void supermethod(){
System.out.println("changed supermethod in sub class");
}
}
请指出,以这两种方式创建子类对象有何不同。访问方法和变量会有什么不同吗? (我们的java老师说,访问方法和变量在两种情况下都会有所不同)
此外,静态方法会发生什么,例如main。我知道它是可继承的,但有人可以突出它在子类中的行为吗?
答案 0 :(得分:16)
在Java中,所有非静态方法都是“虚拟”,这意味着它们基于底层对象的运行时类型,而不是指向该对象的引用类型。因此,在对象声明中使用哪种类型无关紧要,行为将是相同的。
声明的作用是,在编译时可见的方法。如果SubClass
有SuperClass
没有的方法(让我们称之为subMethod()
),那么您将对象构建为
SuperClass s = new SubClass();
然后,您只能调用SuperClass
上可用的方法。也就是说,尝试调用s.subMethod()
会给你一个编译时错误。但是,正如您所发现的那样,如果SuperClass
中存在方法,但SubClass
覆盖了方法,那么它将是将被执行的重写方法。
另一方面,静态方法不是虚拟的。运行以下代码
public class StaticTest {
public static void main(String[] args) {
SuperClass s = new SubClass();
s.method(); // bad idea - calling static method via an object reference
}
public static class SuperClass {
public static void method() {
System.out.println("SuperMethod");
}
}
public static class SubClass extends SuperClass {
public static void method() {
System.out.println("SubMethod");
}
}
}
打印出“SuperMethod”。但是,您应该很少关注static
方法是非虚拟的,因为您不应该像上面那样通过对象引用来调用它们。你应该通过班级名称来呼叫他们:
SuperClass.method();
答案 1 :(得分:2)
我在这里通过一些修改重写你的代码。 请看一下这些变化。
public class superclass {
int num=2;
public static void main(String str[]){
superclass s=new sub();
//HERE: nothing changes if we write, sub s=new sub();
s.supermethod();
s.method();
}
...
...
//This method is not overridden.
void methodInSuper(){
System.out.prinln("method not overridden.");
}
}
class sub extends superclass{
int num=5;
...
...
//This is only in subclass.
void methodInSub(){
System.out.println("method only in subclass.");
}
}
现在,当您创建这样的对象时:
superclass s1=new sub();
然后你可以调用所有被覆盖的方法,比如
s1.supermethod();
s1.method();
在这种情况下,将调用子类的方法。
你也可以调用那些没有被覆盖的超类方法,比如
s1.methodInsuper();
但是如果您尝试访问仅在子类中定义的方法,如
s1.methodInsub();
然后它将是一个编译时错误。
它是becoz s1属于Superclass类型。
如果您仍想在子类中调用该方法,则需要将s1类型转换为子类,如
Sub s = (Sub) s1;
之后你可以调用子类的方法 如果你创建一个像
这样的对象Sub s2 = new Sub();
然后,您可以访问子类或超类中定义的任何方法。
早期创建的对象基本上用于实现" Run Time Ploymorphism"。
希望你得到答案。
答案 2 :(得分:1)
你正在创建sub的sub并将它分配给super的引用。如果你不这样做 1)第一种情况: -
superclass s=new sub();
s.supermethod();
s.method();
在上面的情况下会调用sub的方法但是这两个方法也应该存在于超类中(如果不存在那么编译时错误)
2)第二种情况: -
sub s=new sub();
s.supermethod();
s.method();
在这也是sub的方法,这些方法可能会或可能不会出现超级。
答案 3 :(得分:0)
让我们举一个例子: sup是A类对象的参考变量。和sub是B类对象的引用变量。让我们假设B扩展了A。所以,如果我们写" sup = sub;"或" sup = new B();"这个语句使我们能够获得两个类之间共同的属性。即:B继承的属性......我们使用这个技巧来检查B继承的属性并进行了更改。