Java面向对象三大特征之继承(一)

在之前的文章我们从建立一个类开始,讲述了创建对象的有关知识,(点此进入了解《Java——从建立一个类开始》
以及关于Java面向对象第一个特征封装(点此了解 《封装》 )
在这篇文章中,我们讲述关于继承的相关知识子类与父类的种种联系以及子类的微观实现
(关于子类构造方法以及super关键字的相关知识将会在下一文讲述)


继承

继承的概述

继承的概念

子类继承父类的特征和行为,使得子类具有父类相同的属性。
代码格式如下,

class 父类 {
}
 
class 子类 extends 父类 {
}

为什么要继承

在不同类中会有共同的属性或者方法,我们可以将这些共同的属性和方法放在同一个父类,然后再派生出其他子类来共享

优点

避免重复,易于维护,易于理解。

缺点:

耦合性,即父类发生改变,子类也会随即发生改变。

  • 继承类型:单继承、多重继承 和 多继承一 ,不支持 一继承多。

继承的微观

子类继承父类,除了构造方法的部分,剩下的都会继承。

但是私有的属性,无法在子类中直接访问,但是可以通过间接的手段来访问(可继承,但无法访问)

继承类型

继承类型

java不支持多继承。
我们写的类是现实事物的抽象,而我们真正在公司中所遇到的项目往往业务比较复杂,也会涉及到一系列复杂的概念,都需要我们用代码表示,所以在实际项目中写的类比较多,类之间的关系也十分复杂 。
但是即使如此,我们并不希望类之间的继承层次太复杂,一般我们不希望超出三层的继承关系,如果继承层数过多,就考虑对代码进行重构了。
如果想从语法上限制继承,就可以使用final关键字

Object类

若java中的某个类没有显式的继承任何类,则默认它继承Objec类
Object类是Java语言提供的根类(老祖宗类),也就是说所有对象都会有Object类型中所有的特征。


访问子类对象

遵循就近原则,有则访问自己的,没有则访问父类的。

访问子类对象的成员变量

  1. 如果访问的成员变量,子类中没有,则访问从父类继承下来的,
    倘若父类也没有,则报错。
  2. 同名:如果访问的成员变量与继承父类中的成员变量同名,则优先访问自己的。
    即遵循就近原则。
    示例代码如下,
class A {
    static int E = 10;
    static int I = 8;
}
class B extends A{
    static int E = 20;
}
public class Main {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.E);
        System.out.println(b.I);
    }
}

//输出20 和 8
这段代码定义了一个A类,其中有两个被static修饰的变量E和I值为10和8,
以及继承A类的B类,B类中也有类变量E值为20,
后通过公共Main类中的main函数来,来创建一个B类对象,并访问其中的E和I的值。
结果表明E是B类中的变量,符合第二种情况,I是A类中的变量,符合第一情况。

(这里用类名.类变量名访问变量值在《Java——从建立一个类开始》有提及

访问子类对象的成员方法

  1. 方法名不同时,在子类方法中或者通过子类对象访问方法时,则优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错
  2. 方法名相同时,父类和子类方法中的参数列表不同,根据调用方法时传递的参数选择合适的方法进行访问,如果没有则报错。
  3. 通过子类对象访问父类与子类同名方法时,如果父类和子类同名方法的参数列表、返回值都相同,则遵循就近原则访问子类中的方法,不会访问父类中的方法。
class A {
	void beA() {
        System.out.println("This is A");
    }
    
    void difference(int number) {
        System.out.println("A is not number");
    }
    
    void be() {
        System.out.println("This is A");
    }
}
class B extends A{
	void beB() {
        System.out.println("This is B");
    }
   
    void difference(char letter) {
        if(letter != 'B') System.out.println("B is not " + letter);
    }
    
    void be() {
        System.out.println("This is B");
    }
}
public class Main {
    public static void main(String[] args) {
        B b = new B();
        b.beA();
        b.beB();
        b.difference(5);
        b.difference('C');
        b.be();
    }
}
/*输出:This is A
		This is B
		A is not number
		B is not C
		This is B*/
这段代码定义了一个A类和一个继承A类的B类,
其中子类和父类分别有同名同参数的be()函数,不同名同参数的beA()函数和beB()函数,以及同名不同参数的difference()函数,
分别对应着上文第一二三种情况。
后通过公共Main类中的main函数来,来创建一个B类对象,并依次调用B类对象中的上述函数
输出依次表明上文的结果。

类的初始化

我们将一个类分为静态代码块实例代码块两个部分。

静态代码块和实例代码块都是在Java中用来初始化类或对象的特殊代码块。

静态代码块

静态代码块是使用关键字static定义的代码块,它在类加载的时候执行只会执行一次。
静态代码块通常用于初始化静态变量或执行一些静态操作。

实例代码块

实例代码块是在类中定义的非静态代码块,它在创建对象的时候执行每次创建对象都会执行一次。
实例代码块通常用于初始化实例变量或执行一些实例操作。

class A {
	static int E;
	static int I;
    void beA() {
        System.out.println("This is A");
    }

    void difference(int number) {
        System.out.println("A is not number");
    }

    void be() {
        System.out.println("This is A");
    }
}

比如上文的示例代码,其中A类中static修饰的就是静态代码块其余部分就是实例代码块。

没有继承关系下的执行顺序

  1. 静态代码块先执行,且只执行一次,在类的加载阶段执行。
  2. 当有对象创建时,才会执行实例代码块,实例代码块执行完成后,执行构造方法。

有继承关系下父类子类中的执行顺序

  1. 父类静态代码块优先于子类静态代码块执行,而且是最早执行
  2. 父类实例代码块和父类构造方法紧接着执行
  3. 子类实例代码块和子类构造方法紧接着执行
  4. 第二次实例化子类对象时,父类盒子类的静态代码块都将不会执行
    我们可以编写以下的代码来实验一下。
class A {
    public A() {
        System.out.println("执行:A的构造函数");
    }
    {
        System.out.println("执行:A的实例代码块");
    }
    static {
        System.out.println("执行:A的静态代码块");
    }
}
class B extends A {
    public B() {
        System.out.println("执行:B的构造函数");
    }
    {
        System.out.println("执行:B的实例代码块");
    }
    static {
        System.out.println("执行:B的静态代码块");
    }
}
public class Main {
    public static void main(String[] args) {
        B b1 = new B();
        System.out.println("----------------");
        B b2 = new B();
    }
}

输出:  执行:A的静态代码块
		执行:B的静态代码块
		执行:A的实例代码块
		执行:A的构造函数
		执行:B的实例代码块
		执行:B的构造函数
		----------------
		执行:A的实例代码块
		执行:A的构造函数
		执行:B的实例代码块
		执行:B的构造函数

证明结论是对的。


下面是《Java面向对象三大特征》这几篇文章的参考链接:
(1) (2) (3) (4) (5)
(6) (7) (8) (9) (10)
(11) (12) (13) (14)

  • 19
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值