public class Father {
private String fatherName;
String name;
public String getUserName() {
return fatherName;
}
public void setUserName(String fatherName) {
this.fatherName = fatherName;
}
}
public class Son extends Father{
private String sonName;
String name;
public String getName() {
return sonName;
}
public void setName(String name) {
this.sonName = name;
}
public void printOut(){
System.out.println("this:" + this);
//System.out.println("fathername:" + fathername);
}
}
先定义一个父类Father和一个子类Son,每个类都有一个自己的私有变量和一个公开的name
可以看到子类不仅有自己的sonName和name,还有父类的fatherName和Father.name
可以看到子类的name并没有将父类的name覆盖掉,可以通过super.name对父类中的name进行访问
但是父类的私有变量是无法访问的,这是由于封装的访问控制机制,子类从父类继承来的fatherName也是私有的,编译器会检查对私有变量的访问是否符合规则
调用子类的printOut()方法打印this,并在测试方法中直接打印son,可以发现this实际就是当前这个子类实例的引用
那super是不是父类实例的引用呢?
打印一下super试试
发现会会报错,提示缺少‘.’,可以看出super并不是一个实例的引用,只是一个特殊的指示符,用于在子类中访问父类的成员
super本质上是一个特殊的语法元素,用于表示当前对象的父类部分,通过对象的类层次结构来实现的,当子类使用super时,编译器会生成特殊的字节码指令,这些指令会根据对象的实际类型和继承关系找到父类中对应的成员
所以当子类有和父类相同的成员变量或者成员方法的时候,子类不会将父类的成员方法和变量覆盖掉,只是将它们隐藏起来了,优先调用子类的,如果要访问父类的成员方法和变量的话,可以通过super进行调用
(这里注意,只有在父类的成员变量子类也拥有的时候,会把父类的隐藏掉,通过super来实现显式的调用,但是如果父类的成员变量子类没有的时候,就不会隐藏了,直接显式显示,这也就是为什么前面例子中fatherName前面没有Father.但是name前面有Father.,因为子类也有name,但是子类没有fatherName,如果给子类也加上fatherName这个属性的话,就是下面这样)
此外,this()和super()还可以表示调用子类的构造方法和父类的构造方法
最后总结一下:
this实际就是子类实例对象的一个引用,使用方法有this.和this(),前面用来访问成员变量和方法,后面的用来调用构造函数
由于时实例对象的引用,所以不能在静态方法中使用this
大部分情况this是可以省略的,但是当成员变量名和局部变量名相同时就不能省略了
super的使用方法同样是super.和super(),super实际上是是在子类拥有和父类相同的变量或者方法时调用,但是super不是一个实例的引用,实际上super指向的是this中的一部分,用于区分父子类相同的部分