Java学习——面向对象之继承
概述:当多个类存在相同的属性和方法时,我们可以将这些相同的属性和方法抽取成为一个父类,其他类去继承这个父类即可。继承体现的是一种“is a”的关系
关键字:extends
Java中继承的特点:
1.只能单继承,不能多继承。意思是说一个类只能继承一个类,不能同时继承多个类。这也符合现实生活中只能有一个父亲的特征
2.可以多级继承,意思是子类可以继承父类,父类可以继承爷爷类
注意事项:
1.子类只能继承父类非private修饰的成员变量和成员方法
2.子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法
3.不要为了少部分功能去继承
继承中成员变量的关系:
当子类的成员变量和父类的成员变量名一致时:(就近原则)
1.先找子类的方法内的变量
2.再找子类的成员变量
3.再找父类的成员变量
继承中this与super的区别:
this:谁调用就代表谁,代表该对象的一个引用,必须出现在第一天条语句上
super:父类的一个标识,代表父类的一个引用,必须出现在第一天条语句上
继承中子类的构造方法:
继承中子类每一个的构造方法的第一行都有一个默认的super();,默认去调用父类的空参构造。如果将super();改写为super(a);就会去调用父类一个参数的构造方法
final关键字:
这里我们需要了解一下final关键字
1.final修饰类:该类不能被继承
2.final修饰方法:该方法不能被重写
3.final修饰变量:该变量不能被重新赋值,本质就是一个自定义常量
我们还应当注意:
1.当final修饰的是基本类型数据时:其值不能改变
2.当final修饰的时引用数据类型时:其地址值不能改变
下面我们来看下两道面试题:
//A:案例演示
//看程序写结果1
class Fu{
public int num = 10;
public Fu(){
System.out.println("fu");
}
}
class Zi extends Fu{
public int num = 20;
public Zi(){
System.out.println("zi");
}
public void show(){
int num = 30;
//这里打印的是本方法中的num:30。就近原则
System.out.println(num);//30
//若使用可this关键字,则代表该类对象的成员变量,即打印Zi类中的成员变量num:20。
//时刻记住,this是谁调用就代表谁,如果不写默认为本类,这里的this.num也可以写成Zi.this.num
System.out.println(this.num);//20
//使用super代表的是父类的引用,Zi类继承的是Fu类,所以这里打印的是Fu类中的成员变量num:10
System.out.println(super.num);//10
}
}
class Test {
public static void main(String[] args) {
Zi z = new Zi();
z.show();
}
}
/*
输出结果:
30
20
10
*/
//B:案例演示
//看程序写结果2
class Fu {
static {
System.out.println("静态代码块Fu"); //1
}
{
System.out.println("构造代码块Fu"); //3
}
public Fu() {
System.out.println("构造方法Fu"); //4
}
}
class Zi extends Fu {
static {
System.out.println("静态代码块Zi"); //2
}
{
System.out.println("构造代码块Zi"); //5
}
public Zi() {
System.out.println("构造方法Zi"); //6
}
}
//当Zi z = new Zi();时 请执行结果。
/*
解析:
当new一个子类是,默认先加载父类,所以父类的静态代码块先执行,然后加载子类,子类的静态代码块再执行;
紧接着父类开始初始化,父类构造代码块执行,在下来父类构造方法执行
最后初始化子类,子类构造代码块执行,在下来子类构造方法执行
*/
/*
所以最后输出结果为:
静态代码块Fu
静态代码块Zi
构造代码块Fu
构造方法Fu
构造代码块Zi
构造方法Zi
/*
结尾:如果读者不太知道执行代码块执行顺序的可以参考我上篇博客