java面向对象特性——继承
1.继承
1.1继承的概述
继承是面向对象的三大特性之一,可以使得子类去继承
父类的属性和方法,还可以在子类中添加自己特有的属性。
继承是对每个类进行共性的抽取。好处就是可以实现代码的复用。
1.2语法
修饰符 class 子类 extends 父类{
}
比如:
public class Dog extends Animal{
}
Dog : 称为子类或派生类
Animal :父类/基类/超类
注意:
- 子类会将父类的方法和属性继承到子类中。
- Java中是没有多继承的,只有单继承。
- 继承是类与类之间的一种关系。
- 继承是“is a”的关系。
- 子类继承父类用到的关键字是“extends”.
- 当子类去继承父类的属性和方法时,还可以在子类中添加自己特有的属性,否则就没有必要继承了。
- 当子类继承父类,通过子类对象是可以访问父类中的方法和对象的。
代码:
创建一个Animal类作为父类
public class Animal{
public String name;
public int age;
public void eat(){
System.out.printlln(this.name + "正在吃饭");
}
}
创建子类Cat类
public class Cat extends Animal{
public void mimi(){
System.out.printlln(this.name + "正在喵喵叫.......");
}
}
测试Test类
public class Test
public static void main(String[] args){
Cat cat = new Cat();
cat.name = "小猫";
cat.eat();
}
}
1.3 继承中成员变量的访问特点
1.3.1子类和父类不存在同名变量
当子类访问一个变量的时候,最先在子类的局部变量中寻找,如果在子类的局部变量中没有,则在子类的成员变量中查找,最后在父类的成员范围找。
创建Base父类
public class Base{
public int a =10;
public int b =20;
}
创建子类Derieved类
public class Derieved extends Base{
public int a =1;//如果没有这条语句和 int a = 2,则输出10
public int c =20;
public void func(){
int a = 2;//如果没有这条语句,则a的值输出为1
System.out.println(a);
}
}
1.3.2子类和父类存在同名变量
当子类和父类都同在变量相同的名字时,会先访问自己的。
如果想要访问父类特有的,这时,会使用关键字super。
可以通过super访问子类继承过来父类的成员。
总结 |
1.4 继承中成员方法的访问特点
父类Base
public class Base{
public void test(){
System.out.println("父类的无参方法");
}
}
Derieved类
public class Derievedextends Base{
public void test1( char a){
System.out.println("子类的无参方法");
}
public void test(){
System.out.println("子类的无参方法");
}
public void methodC(){
test();//调用这个方法时,会调用自己的test()方法,没有则找父类
test1('a'); //有参就会直接调用有参的方法
}
}
总结:
- 成员方法没有同名时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
- 如果父类和子类同名方法的参数列表不同(重载),根
据调用合适传递的参数选择合适的方法访问,如果没有则报错。
1.5super关键字
super关键字,该关键字主要作用:在子类方法中访问父类的成员。
1.5.1super和this
super关键字和this关键字的用法很相似。
相同点
- 都是java的关键字
- 只能在类的非静态方法中使用,用来访问非静态的成员变量和方法。
- 都必须在构造方法的第一行,不能同时存在。
- 访问成员变量的时候都是通过“ . ”号进行访问的。
不同点:
- this是当前对象的引用,super是子类对象从父类成员继承下来的引用,也即只能指代当前类的父类。
- 在非静态的成员方法中,this用来访问本来的方法和属性,super是用来访问父类继承下来的方法和属性。
- this调用本类的构造方法,super是调用父类的构造方法。
- 构造方法中一定会存在super()的调用,用户没有自己写编译器也会添加,而this() 用户不写则不会添加。
1.5.2子类的构造方法
当构造子类对象的时候,我们需要先调用父类的构造方法,然后在调用子类的构造方法。所以,在子类对象构造完成之前,子类需要显示的调用父类构造方法,先帮助父类的成员进行初始化。
创建父类
public class Fu{
public Fu(int a){
System.out.println("父类有参的构造方法.....");
}
}
子类
public class Zi{
public Zi(){
super(10);
System.out.println("子类无参的构造方法.....");
}
}
测试类Test
public class Test{
public static void main(String[] args){
Zi zi = new Zi();
}
}
结果是:
父类有参的构造方法.....
子类无参的构造方法.....
当父类的构造方法是不带参数的构造方法且只有这一个的情况下,默认会添加一个super()。
父类
public class Fu{
public Fu(){
System.out.println("父类无参的构造方法.....");
}
}
子类
public class Zi{
public Zi(){
//super(); 不写这个一行也是不会报错的,编译器会自己添加。
System.out.println("子类无参的构造方法.....");
}
}
注意事项:
- 通过super(参数)的形式可以调用父类指定的构造方法。
- 当父类是有参的构造方法,,此时需要用户为子类显式定义构造方法,并在子类构造方法中选择合适的父类构造方法调用,否则编译失败。
- super(…)只能在子类构造方法中出现一次,并且不能和this同时出现。
1.6再谈初始化
在之前学习的,在当前类中静态代码块,实例代码块,构造方法同时出现的情况下,会先执行静态,然后实例,最后构造。
在继承的关系上,会先执行什么呢?
创建父类Animal类
class Animal{
public String name;
public int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
System.out.println("Animal:构造⽅法执⾏");
}
{//实例代码块
System.out.println("Animal:实例代码块执⾏");
}
static {//静态代码块
System.out.println("Animal:静态代码块执⾏");
}
}
创建子类Dog类
public class Dog extends Animal{
public Student(String name,int age) {
super(name,age);
System.out.println("Dog:构造⽅法执⾏");
}
{
System.out.println("Dog:实例代码块执⾏");
}
static {
System.out.println("Dog:静态代码块执⾏");
}
}
测试类:
public class Test {
public static void main(String[] args) {
Dog dog = new Dog ("旺财", 10);
System.out.println("========");
Dog dog = new Dog ("狗", 11);
}
}
执行结果:
Animal:静态代码块执⾏
Dog:静态代码块执⾏
Animal:实例代码块执⾏
Animal:构造代码块执⾏
Dog:实例代码块执⾏
Dog:构造代码块执⾏
==============
Animal:实例代码块执⾏
Animal:构造代码块执⾏
Dog:实例代码块执⾏
Dog:构造代码块执⾏
1.7 protected关键字
如果被protected 关键字修饰该类当中成员变量,成员方法。要么只能在同⼀个包中的类中进行访问,要么在不同包中只能通过在继承关系上的子类对象来访问。
1.8继承方式
- 单继承
- 多层继承
- 不同类继承同一个类
但是在java中是不支持多继承的。
1.9final关键字
public final class Dog extends Animal
如果一个类不幸被其他类继承,此时,可以使用关键字final来修饰当前这个类,此时,这个类叫作密封类。被final修饰的方法将不能重写。
final int a =10 ;
被final修饰的变量是常量,说明这个变量的值将不能被修改。