我正在尝试理解java中的方法覆盖。 理解私有方法不能被覆盖。
public class Superclass
{
private String name;
Superclass(String name) {
this.name=name;
}
private void printName(String name) {
System.out.println("This is a Superclass output"+name);
}
}
public class Subclass extends Superclass
{
Subclass(String name) {
super(name);
}
public void printName(String name) {
System.out.println(name);
}
}
public static void main (String[] args) {
Superclass sb = new Subclass("Superclass");
//System.out.println(sb.getClass().getName());
sb.printName("this is super class variable");
}
我正在尝试执行这段代码
和输出:"This is a Superclass outputthis is super class variable"
请帮助我了解对象实际引用的类。
以及printName
在超类中公开时看到的输出是:
"this is super class variable"
也请帮助我理解为什么sb
指向两个不同的类,取决于私有和公共修饰符。
答案 0 :(得分:3)
覆盖是运行时(动态)多态性。我们不能覆盖私有方法。因此私有方法使用静态绑定。静态绑定方法与特定对象无关,而是在Type(Java中的类)上调用。
当我们将父类方法公开时,就会发生动态绑定。在运行时,对象的类型确定要执行的方法。
答案 1 :(得分:1)
Superclass sb = new Subclass("Superclass");
此处Superclass
引用变量sb
将在Superclass
对象中搜索Subclass
对象,它会找到它,因为Subclass extends Superclass
以来它就在那里
sb.printName("this is super class variable");
此处sb
指向Subclass
对象,因此如果有重写方法,它将执行该方法。
但是
如果没有重写方法,它将始终执行Superclass
方法,因为引用类型为Superclass
。
参考:http://www.codejava.net/java-core/the-java-language/12-rules-of-overriding-in-java-you-should-know
答案 2 :(得分:0)
您无法访问其类外的私有方法。
看看下表*:
| Class | Package | Subclass | Subclass | World
| | |(same pkg)|(diff pkg)|
————————————+———————+—————————+——————————+——————————+————————
public | + | + | + | + | +
————————————+———————+—————————+——————————+——————————+————————
protected | + | + | + | + |
————————————+———————+—————————+——————————+——————————+————————
no modifier | + | + | + | |
————————————+———————+—————————+——————————+——————————+————————
private | + | | | |
+ : accessible
blank : not accessible
因此,如果你想打印"This is a Superclass outputthis is super class variable"
,你必须让你的超级printName()
至少包私有(=无修饰符)。
到你的第二个问题:
请帮助我了解对象实际引用的类。我看到printName在超类中公开时的输出是:
"这是超类变量"
java会自动获取子类的功能,因为您在以下位置创建了它的实例:
Superclass sb = new Subclass("Superclass");
答案 3 :(得分:0)
首先,你应该自己探索更多,这样当输出本身回答问题时你就不需要问这样的问题了。 你的问题是关于哪个对象,而不是为什么这个行为。 那么回答你的问题。考虑以下2个senarios
案例1: Super super=new Super();
案例2: Super superSubclass=new Subclass(); //extends Super and instance refered by Super
案例3: Subclass subclass=new Subclass();// Referenced by own
案例1:这个类不知道地球上的任何其他实现,所以它可以访问的是它自己在Super类中声明的方法(ALL表示ALL包括Private)。因此,只有这一课才能看到混乱。
案例2:根据语句Subclass是Super的扩展实现,实例是由Super引用创建的。 在这种情况下,除了CASE 1之外,superSubclass还可以在扩展实现中访问重写方法。表示SUBCLASS中所有SUPER +重写方法的方法
案例3:考虑它就像案例1.引用与它的实例相同,它可以访问它的ALL方法+它的子类的非私有方法。
我用同样的语气回答了这个问题,试图澄清你的困惑。 但我认为你需要理解的主要内容是为什么这种行为最终将清除你的概念。 但是,当我看到你是初学者时,一旦你开始预测上面提到的输出,你就会学习。
干杯!
答案 4 :(得分:0)
因为private
方法的调用是在编译时确定的。 (顺便说一句,构造函数和super
方法也是在编译时确定的。)
我将通过字节码解释它。
首先是源代码:
public class Q47069297 {
public static void main(String[] args) {
SuperClass sc = new SubClass();
sc.print();
}
private static class SuperClass {
private void print() {
System.out.println("super");
}
}
private static class SubClass extends SuperClass {
private void print() {
System.out.println("sub");
}
}
}
调用SuperClass.print
:
10 invokestatic xdean.stackoverflow.java.Q47069297$SuperClass.access$1(xdean.stackoverflow.java.Q47069297$SuperClass) : void [21]
怎么了?我们致电print
,但有SuperClass.access$1
!
我们转到SuperClass
的字节码,找到access$1
static synthetic void access$1(xdean.stackoverflow.java.Q47069297.SuperClass arg0);
0 aload_0 [arg0]
1 invokespecial xdean.stackoverflow.java.Q47069297$SuperClass.print() : void [32]
4 return
Line numbers:
[pc: 0, line: 10]
哇,真的有一个方法,一个名为access$1
的合成方法。所以我们发现类本身的私有方法调用只是java编译器的一个骗局。它在类中生成一个包友好的静态方法并调用它。所以源代码应该是:
SuperClass sc = new SubClass();
SuperClass.access$1(sc);// sc.print();
它不会调用SubClass
,因为它确实是一个静态方法调用。