一.继承
1.为什么要继承
比如:我们定义了一个猫类和狗类,每个动物都有名字和年龄及他们的行为:
写一个Animal类,使用extends来继承Animal。
可以看出:继承就是专门用来进行共性抽取,实现代码复用
2.继承的语法
Java中要表示继承关系,就要使用extends关键字,具体如下:
被继承的类(如上面的Animal类)叫父类/基类/超类,上面的Dog类和Cat类在继承中叫子类/派生类。
3.继承的使用
3.1父类成员访问
继承体系中,子类继承了父类的成员方法和成员字段(变量),我们就可以在对应的成员方法中直接使用。(对应指的是:如父类的成员未被static修饰(被修饰的要用类名调用),那它不能在静态成员方法中直接使用,因为在调用成员方法时,其实隐藏了this,而this不能在静态成员方法中使用)
第二:在非子类中通过子类对象访问成员:
2.子类和父类成员变量同名时:
在子类方法中 或 通过子类对象访问成员:
1.优先调用子类的成员(可以理解为就近原则)。
2.如果调用的成员子类中没有,就会从父类中找,如果父类中也没有定义,则编译报错。
3.发生方法重载,可以用括号中的参数区分调用的是哪个方法。
都调用了子类自己的成员。
那如果成员名一样,而我又想在子类方法中调用父类的成员该怎么办呢?--->使用super关键字。
4.super关键字
有时因场景需要,子类和父类有相同的成员名。我们不能直接访问父类的成员,可用super关键字,它是专门用来访问父类成员的:
【注意事项】
super:
1.只能在非静态方法中使用。
2.只能在子类方法中,访问父类的成员变量和方法。
super的其他用法在下面中介绍。
4.1子类的构造方法
父子-->先有父再有子!即:要想调用子类的构造方法,系统就会自动先执行父类的构造方法,后再执行子类的构造。
我们知道,在类中我们不创建构造方法系统也会自动给我们创建一个无参的构造。父类的构造会被子类继承,在构造子类对象时,先执行基类的构造方法,然后执行子类的构造方法。
因为:子类对象中成员是有两部分组成的,基类继承下来的以及子类新增加的部分 。
【注意】!!
1.若父类显式定义无参或默认的无参构造方法,在子类构造方法第一行默认有隐含的super()调用,即调用基类构造方法。 (这就是为什么上面会先访问父类的构造的原因)当然我们自己在第一行写super();也ok;例:
还有一种,只有父类或子类写了无参构造方法,另一半也会自动生成构造的。
2. 如果父类构造方法是带有参数的,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。例:
正确的方式:
4.2super和this的区别
5.再谈初始化
我们回顾一下:一个类中可以定义静态代码块、构造代码块(也叫实例代码块)和构造方法,他们的执行顺序是: 1.静态代码块--》2.实例代码块--》3.构造方法(具体我Java2.2这篇最后有讲)
6.继承方式
在现实生活中,事物之间的关系是非常复杂,灵活多样的,比如:
但在Java中只支持以下几种继承方式:
尽管可以持续多继承,但继承关系一般不会超过三层,如果想从语法上进行限制继承, 就可以使用 final 关键字(下面会讲,final)
7.protected关键字
那父类中不同访问权限修饰的词,在子类中的可见性又是怎样的?
同一个包中的子类:
不同包中的子类:
不同包中的非子类:
注意:父类中private成员变量虽然在子类中不能直接访问,但是也继承到子类中了。
(不能直接访问的意思是,还可以通过get和set来访问成员)
8.final 关键字
1. 修饰变量或字段,表示常量(即不能修改)
2. 修饰类:表示此类不能被继承
3. 修饰方法:表示该方法不能被重写(在下一篇多态中会讲到)
9.继承和组合
继承则是 奔驰是车: