第十三节 java继承

继承概念

继承体现的关系:继承体现的是is a 的关系,对2个类A,B,假如可以这样描述:B是一个A, 则可以用继承表示二者的关系。

继承的作用

将所有子类公有的属性和方法定义在父类中,其子类通过继承获得这些属性和方法,实现代码的复用。

继承实现

Java中继承的实现, 关键字: extends

访问修饰符  类名 extends 父类{}

继承特点

单一继承

一个类只能继承一个父类,一个父类可以有多个子类。

class Base{
    
}
/**
 * Son继承Base,Son是子类Base是父类
 */
class Son extends Base{
    
}

Object

2.Object是所有类的根,假如类名后没写extends,默认继承Object。

package com.njlife123.qzmall.clazz;

public class Test3 {

    public static void main(String[] args) {
        Base base = new Base();
        //Base类没有toString和equals方法,都是 
        //Object类的,所以所有的类都继承Object类
        //类的方法都可以调用Object类的所有方法和属性。
        base.toString();
        base.equals("123");
    }
}

继承可以传递

子类可以获得所有父类(直接父类、间接父类)的属性和方法。
代码:

package com.njlife123.qzmall.clazz;
public class Test3 {
    public static void main(String[] args) {
        Son son = new Son();
        System.out.println(son.a);
        System.out.println(son.b);
        son.f();
    }
}
class Base{
    int a;
    String b;
    public void f(){}
}
/**
 * Son继承Base,Son是子类Base是父类
 */
class Son extends Base{

}

继承中的构造函数

注意:构造函数不能被继承,但是在子类的构造函数中可以调用父类的构造。

语法:在子类的构造函数的第一行,用super(参数列表)调用父类的某个构造。

比如:

class User{
    private String userName;
    private String password;
    private String num;
    public User() {
    }
    public User(String userName, String password, String num) {
        super();//这里调用父类Object得super()空参构造器。
        this.userName = userName;
        this.password = password;
        this.num = num;
    }
}
class ZhangSan extends User{
    public ZhangSan(){
    }
    public ZhangSan(String userName, String password, String num){
        //调用父类构造器
        super(userName,password,num);
    }
}

调用本类构造器

class User{
    private String userName;
    private String password;
    private String num;
    public User() {
    }
    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public User(String userName) {
        //调用 User(String userName, String password)构造器
       this(userName,"123");
    }
}

super的隐式调用

假如构造函数中,没有在第1行写this()或者super(), 此时编译器会添加一个隐式的super();
即调用父类的空参构造。此时假如父类没有空参构造,则会编译报错。

比如:

class User{
    private String userName;
    private String password;
    private String num;
    
    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public User(String userName) {
       this(userName,"123");
    }
    public User(String userName, String password, String num) {
        super();//这里调用父类Object得super()空参构造器。
        this.userName = userName;
        this.password = password;
        this.num = num;
    }
}
class ZhangSan extends User{
    //父类没有空参构造器,子类报错
    public ZhangSan(){
    }
}

显示调用和隐式调用父类构造器。

class User{
    private String userName;
    private String password;
    private String num;
    public User() {
    }
    public User(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public User(String userName) {
       this(userName,"123");
    }
    public User(String userName, String password, String num) {
        super();//这里调用父类Object得super()空参构造器。
        this.userName = userName;
        this.password = password;
        this.num = num;
    }
}
class ZhangSan extends User{
    public ZhangSan(){
       // super();隐式调用父类空参构造器。
    }

    public ZhangSan(String userName, String password){
        // super();隐式调用父类空参构造器。
    }

    public ZhangSan(String userName, String password, String num){
       super( userName,  password,  num);//显示调用父类构造器。
    }
}

当构造一个类的实例时, 会递归调用父类的构造,直到Object。

public class Test1 {

    public static void main(String[] args) {
        A3 a3 = new A3();
    }
}
class A1{
    public A1(){
        super();//可以不写,隐式调用
        System.out.println("A1");
    }
}
class A2 extends A1{
    public A2(){
        super();//可以不写,隐式调用
        System.out.println("A2");
    }
}
class A3 extends A2{
    public A3(){
        super();//可以不写,隐式调用
        System.out.println("A3");
    }
}

打印结果:

A1
A2
A3

Process finished with exit code 0

abstract

abstract修饰方法: 当定义类中某个方法的时候,代码是不确定的,就可以将其声明成抽象方法。 只有声明,没有实现;通常这些方法交由子类去实现。

语法:访问修饰符的部分添加abstract 返回类型 方法名();

比如:

abstract class  Shape{
    double perimeter;
    double area;
    public abstract double area();//抽象方法
    public abstract double getPerimeter();//抽象方法
}

class Circle extends  Shape{
    
    @Override
    public double area() {//实现抽象方法
        return 0;
    }
    @Override
    public double getPerimeter() {//实现抽象方法
        return 0;
    }
}

一个类中只要有抽象方法,这个类就必须声明成抽象类。

因为抽象类中有未实现的方法,所以抽象类不能实例化。
验证:

public class Test1 {

    public static void main(String[] args) {
        Shape shape = new Shape();//报错了
    }
}
abstract class  Shape{
    double perimeter;
    double area;
    public abstract double area();//抽象方法
    public abstract double getPerimeter();//抽象方法
}

一个类中没有任何抽象方法,仍然可以声明成抽象类.唯一目的不能实例化。

abstract 能否与static 同用? 不能
abstract 类不能被实例化,也就意味着不能被分配内存,二static在类实例化之前必须分配内存,两者冲突,所以不能一起使用。

abstract 能否与private 同用? 不能
private 修饰得变量和方法都只能在本类访问不能被其他类访问,而abstract 得方法和属性就是给子类使用得,你不让使用不久冲突了吗。

final

final修饰变量

1.final修饰成员属性必须初始化。
2.修饰局部变量使用前必须初始化。

class Circle{
    private final int a = 1;//声明必须初始化
    private  int b;
    private void f(){
        final int  a;
        System.out.println(a);//使用前必须初始化,不然 编译不通过
    }
}

final修饰引用类型,其指向的对象的数据是可以修改的,但它的地址不能变,即它不能再指向其它对象,代码:

public class Test1 {

    private int a = 33;

    public static void main(String[] args) {
         final Test1 test1 = new Test1();
         test1 = new Test1(); //报错,指针不可修改
        test1.a = 44;//对象数据可以修改
    }
}

final修饰方法

方法不能被子类重写。

class Base{
    public final void f(){
    }
}

class Child extends Base{
    public void f(){ //不能重写父类final修饰得方法,编译不通过
    }
}

final修饰类

final修饰的类是最终类,不能再被继承了。

final class Base{
    public final void f(){
    }
}
class Child extends Base{ //不能被继承,父类是final修饰,编译不通过
}

接口

概念

接口体现的关系:接口体现的是has a 的关系。一个类实现了某个接口,表示类具有接口中所定义的功能。

语法

访问修饰符 interface 接口名{
		//定义属性
		//定义方法
}

属性的默认访问修饰符: public static final, 表示接口中的属性均为静态常量。

方法的默认访问修饰符: public abstract, 表示接口中的方法均为抽象方法。

比如:

interface IBase{
    int i = 10; //等价于 public static final int i = 10;
    void test();//等价于public abstract void test();
}

接口的实现

访问修饰符 class 类名 implements 接口1, 接口2,.{

}

一个类可以同时实现多个接口,多个接口之间用逗号隔开

interface IBase1{
}
interface IBase2{
}
class Base implements IBase1,IBase2{

}

接口也可以继承,通过继承获得父接口中定义的方法,支持多个父接口,逗号。

interface IBase1{
}
interface IBase2{
}
interface Base extends IBase1,IBase2{

}

作者简介:一个有故事的程序员,我的微信号qiushuzhao222,欢迎大家找我聊天,记录你我的故事。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值