super的作用
-
直接父类对象的引用,通过super可以访问父类中被子类覆盖的方法或属性
-
使用super调用普通方法,语句没有位置限制,可以在子类中随便调用。
-
若是构造方法的第一行代码没有显式的调用super(...)或this(...);那么Java默认都会调用super(),含义是调用父类的无参数构造方法。这里的super()可以省略
-
这里面涉及到继承树追溯的问题
-
实例:
package cn.Lucifer.oo;
public class TestSuperNo1 {
public static void main(String[] args) {
new ChildClass().f(); //创建了一个子类对象,调用了子类方法,在子类的f方法里面又调用了父类的f方法
}
}
//写一个父类
class FatherClass{
public int value;
//写一个方法,打印一个值
public void f(){
value = 100;
System.out.println("FatherClass.value=" + value);
return;
}
}
//写一个子类继承自父类
class ChildClass extends FatherClass{
public int value;
//重写父类的方法
public void f(){
super.f(); //调用父类对象的普通方法
value = 200; //这个value指的是这个类的成员变量
System.out.println("ChilClass.value=" + value);
System.out.println(value);
System.out.println(super.value); //父类的成员变量(属性)
/*
可以通过super.value可以指向被覆盖的父类的属性的值
通过super指向父类的对象
*/
}
}
继承树追溯---同一个包里面不能有同名的类
属性/方法查找顺序:(查找变量H)
-
查找当前类中有没有属性h
-
依次上溯每个父类,查看每个父类中是否有h,直到Object
-
没找到---编译错误
-
找到---过程终止
-
构造方法调用顺序
-
构造方法第一句总是:super(...)来调用父类对应的构造方法
-
先向上追溯到Object
-
再依次向下执行类的初始化块和构造方法,直到当前子类为止
静态初始化块调用顺序与构造方法调用顺序一样,不再重复
实例:
package cn.Lucifer.oo;
/**
* 测试Super(...)
* @author Lucifer
*/
public class TestSuperNo2 {
public static void main(String[] args) {
System.out.println("开始创建一个ChildClass对象......");
//创建一个ChildClass对象
new ChildClassNo2();
// return;
}
}
//创建一个父类
class FatherClassNo2{
//父类中只写一个方法---下面是一个构造器
public FatherClassNo2(){
System.out.println("Create FatherClass");
return;
}
}
//创建一个子类继承自父类
class ChildClassNo2 extends FatherClassNo2{
//里面也写一个构造器
//super(); 这句话不加编译器会自动去加上
public ChildClassNo2(){
System.out.println("Create ChildClass");
return;
}
}
/*
实际上两个类的方法都被打印了,而且先打印父类的方法。那么父类的方法是怎么被调用的?
1.因为构造方法的第一句总是super();,无论你写还是不写。
2.super()会默认去调用父类的构造器
*/
图示: