Java中的代码块、继承以及方法重写

这一块的内容主要是有关Java中的代码块、继承,以及方法重写的内容。

1.代码块

Java中,使用{}括起来的称为代码块,根据其位置和声明的不同,可以分为局部代码块、构造代码块、静态代码块、同步代码块(多线程再涉及)

  • 局部代码块
    在方法中出现:限定变量的生命周期,及早释放,提高内存利用
    只有这一种在一个类出现的时候执行顺序是自上而下的

  • 构造代码块
    在类中方法外出现,多个构造方法中相同的代码存放到一起,每次调用构造都执行,并且在构造方法前执行

  • 静态代码块
    在方法外出现,加上static修饰,用于给类进行初始化,在加载的时候就执行,并且只执行一次

  • 执行顺序
    局部代码块——静态代码块(有多少执行多少,只执行一次,自上而下)——构造代码块——构造方法

举例

class Code{
    //静态代码块
    static{
        int a = 200;
        System.out.println(a);
    }

    //构造方法
    Code(){
        int b = 300;
        System.out.println(b);
    }

    //构造代码块
    {
        int x = 100;
        System.out.println(x);
    }
}
public class CodeDemo {
    public static void main(String[] args) {
        {
            int x = 100;
            System.out.println(x);
        }
        {
            int y = 200;
            System.out.println(y);
        }
        System.out.println("----------------------");
        Code c = new Code();
        System.out.println("----------------------");
        Code c1 = new Code();
        System.out.println("----------------------");
        Code c2 = new Code();
        System.out.println("----------------------");
    }
}
//100
//200
//----------------------
//200
//100
//300
//----------------------
//100
//300
//----------------------
//100
//300
//----------------------

先执行主函数中的局部代码块,输出100200,之后是new了一个Code对象出来,执行的是静态代码块(一次),再到构造代码块,再到构造方法。

2. 继承

  • 概述
    多个类中存在相同的属性和行为时,将这些内容抽取到单独的一个类,那么多个类无需再定义这些属性和行为,只要继承这个类即可
    通过extends关键字可以实现类与类的继承

      	class 子类名 extends 父类名 {}
    

    单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类
    有了继承之后,我们定义一个类的时候,可以在已经存在的类的基础上,还可以定义自己的新成员。

  • 好处

    • 提高了代码的复用性
    • 提高了代码的维护性
    • 让类与类之间产生关系,为后面的多态做准备
  • 坏处

    • 类的耦合性增强了
      开发的原则:低耦合、高内聚
      耦合:类与类之间的关系
      内聚:就是自己完成某件事情的能力

举例:

class Person1{
    String name;
    int age;
    public Person1(){

    }
    public void study(){
        System.out.println("学习");
    }
    public void eat(){
        System.out.println("吃饭");
    }
    public void sleep(){
        System.out.println("睡觉");
    }
}

class Student1 extends Person1{ //Student1是继承Person1来的,或者说是继承自Person1的子类
    String stuId;
    public void playGame(){
        System.out.println("打游戏");
    }
}

class Teacher1 extends Person1{

}

public class ExtendsTest1 {
    public static void main(String[] args) {
        Student1 student1 = new Student1();
        student1.eat();
        student1.sleep();
        student1.study();

        System.out.println("----------------------------");

        Teacher1 teacher1 = new Teacher1();
        teacher1.eat();
        teacher1.sleep();
        teacher1.study();
    }
}
//吃饭
//睡觉
//学习
//----------------------------
//吃饭
//睡觉
//学习

继承很好的提高了代码的复用性
  • Java中继承的特点:
    • Java只支持单继承,不支持多继承
    • Java支持多层基础(继承体系)

代码举例:


//class Father{}
//class Mother{}
//class Son extends Father{}
//class Son extends Father,Mother{}//错误

class GrandFather{
    public void show(){
        System.out.println("这是爷爷");
    }
}

class Father extends GrandFather{
    public void show1(){
        System.out.println("这是爸爸");
    }
}

class Son extends Father{
    public void show2(){
        System.out.println("这是儿子");
    }
}

public class ExtendsDemo2 {
    public static void main(String[] args) {
        Son son = new Son();
        son.show2();
        son.show1();
        son.show();
    }
}
//这是儿子
//这是爸爸
//这是爷爷
  • 使用继承的注意事项:
    • 子类只能继承父类所有的非私有的成员(非私有的成员方法和非私有的成员变量)
    • 子类不能继承父类的构造方法,但是可以通过super关键字来访问父类的构造方法
    • 不要为了部分功能而去继承

class A{
public void show1(){}
public void show2(){}
}

class B{
public void show2(){}
public void show3(){}
}

通过观察发现,出现了一个show2()方法,在类A和类B中都出现了,用继承实现

class B extends A{
public void show3(){}
}

这样继承,我们发现show1()并不是我们B类中方法,但是我们一并继承过来了

使用继承的情况:is a
满足这一条件就可以使用继承
Person
Student
Teacher
Doctor

代码举例继承的注意事项:

class Father1{
    private int num = 20;
    private int num2 = 30;

    public Father1(){
        System.out.println("这是父类的构造方法");
    }

    private void function(){
        System.out.println(num);
        System.out.println(num2);
    }
}

class Son1 extends Father1{
    int num3 = 300;
    public void fun(){
//        System.out.println(num);//子类不能继承父类的私有成员变量
//        System.out.println(num2);
        System.out.println(num3);
    }
}

public class ExtendsDemo3 {
    public static void main(String[] args) {
        Son1 son1 = new Son1();
        son1.fun();
//        son1.function();//子类不能继承父类的私有成员方法
    }
}
//这是父类的构造方法
//300
  • 继承与成员变量的关系:

    • 类的组成:
      • 成员变量
      • 成员方法
      • 构造方法
        引入继承之后,我们开始考虑继承与这些的关系
        1、当父类的成员变量与子类的成员变量不一样的时候
        2、当父类的成员变量与子类的成员变量一样的时候

    查找顺序:
    1、在子类方法的局部范围找,找到返回
    2、在子类方法的成员范围找,找到返回
    3、在父类方法的成员范围找,找到返回
    4、都找不到,报错

继承与成员变量的关系 代码举例:

class Father2{
    int num = 10;
    public void show2(){
        int num3 = 50;
    }
}

class Son2 extends Father2{
    int num2 = 20;
    int num = 30;
    public void show(){
        int num = 40;
        System.out.println(num);
        System.out.println(num2);
//        System.out.println(num3);
    }
}

public class ExtendsDemo4 {
    public static void main(String[] args) {
        Son2 son2 = new Son2();
        son2.show();
    }
}
//40
//20

3.super关键字

  • 当我们不仅想输出局部范围的num,还想输出父类中的num,我们应该怎么做呢
    Java中提供了一个关键字:super

  • super和this的区别是什么呢?(面试题)
    this代表当前对象的引用
    super代表的是父类存储空间的标识(可以操作父类的成员)

  • 怎么使用?

    • 调用成员变量
      this.成员变量 调用的是本类的成员变量
      super.成员变量 调用的是父类的成员变量
    • 访问构造方法(子父类的构造方法)
      this(…) super(…)
    • 访问成员方法
      this.成员方法() super.成员方法()

super关键字的使用举例代码:

class Father3{
    int num = 10;
}

class Son3 extends Father3{
    int num = 20;
    public void show(){
        int num = 30;
        System.out.println(num);
        System.out.println(this.num);
        System.out.println(super.num);
    }
}

public class ExtendsDemo5 {
    public static void main(String[] args) {
        Son3 son3 = new Son3();
        son3.show();
    }
}
//30
//20
//10
  • 继承与构造方法的关系
    • 子类中所有的构造方法默认都会访问父类中空参的构造方法
    • 为什么?
      因为子类会继承父类的数据,可能还会使用父类的数据
      所以在初始化子类之前,一定会先完成父类的初始化
      注意:
      每一个子类的构造方法的第一句话默认都是super()

继承与构造方法的关系举例:

class Father4{
    int age;

    public Father4(){
        System.out.println("这是父类的无参构造方法");
    }

    public Father4(String name){
        System.out.println("这是父类的有参构造方法");
    }
}

class Son4 extends Father4{
    public Son4(){
        System.out.println("这是子类的无参构造方法");
    }

    public Son4(String name){
        System.out.println("这是子类的有参构造方法");
    }
}

public class ExtendsDemo6 {
    public static void main(String[] args) {
        Son4 son4 = new Son4();
        Son4 son5 = new Son4("祥哥");
    }
}
//这是父类的无参构造方法
//这是子类的无参构造方法
//这是父类的无参构造方法
//这是子类的有参构造方法
  • 但是,当父类没有无参构造方法的时候,怎么办呢

    • 使用super带参的形式去访问父类的带参构造方法
    • 子类通过this去调用本类的其他构造方法
      本类其他构造方法也必须首先访问父类的构造方法
      使用this就是间接的调用super去访问父类的构造方法
  • 注意事项:

    • super(…)或者this(…)必须出现在第一条语句上
    • 否则,就会有父类数据的多次初始化,每个类只能初始化一次

代码举例:

class Father5{
    int age;

    public Father5(){
        System.out.println("父类的无参构造方法");
    }

    public Father5(String name){
        System.out.println("父类的有参构造方法");
    }
}

class Son5 extends Father5{
    public Son5(){
        super();//JVM虚拟机会默认在调用子类构造方法的时候添加一个super(),而且必须放在第一句
        System.out.println("子类的无参构造方法");
    }

    public Son5(String name){
//        this("hb");
        super("hb");//这是调用父类的有参构造方法
        //这里的this或者super只能出现一个,我的解释是:如果出现多个,或者同时出现
        //会造成父类数据的多次初始化,但每个类只能初始化一次
        //使用super可以理解是父类的带参的调用
        //使用this时,也需要继承父类,,也会有super的出现,所以也会造成父类的初始化
        //所以只能有一个
        System.out.println("子类的带参构造方法");
    }
}

public class ExtendsDemo7 {
    public static void main(String[] args) {
        Son5 son5 = new Son5();
    }
}

  • 继承中成员方法的关系:
    • 子类的成员方法与父类的成员方法不一样
    • 子类的成员方法与父类的成员方法一样的时候,怎么办
      • 先找到子类,有没有这个方法,如果有,就调用
      • 如果子类中没有这个方法,就去父类中找,如果有,就调用
      • 如果都没有,就报错

代码举例:

class Father6{
    public void show(){
        System.out.println("this is show()");
    }
}

class Son6 extends Father6{
    public void show2(){
        System.out.println("this is son6 show2()");
    }

//    public void show(){
//        System.out.println("this is son6 show()");
//    }
}

public class ExtendsDemo8 {
    public static void main(String[] args) {
        Son6 son6 = new Son6();
        son6.show();
        son6.show2();
    }
}
//this is show()
//this is son6 show2()

4.方法的重写

方法的重写:
子类中如果出现了和父类中一模一样的方法声明,也被称为方法覆盖,方法复写

方法的重载:
本类中出现了方法名一样,参数列表不一样的方法,与返回值无关

子类的成员方法与父类的成员方法一样的时候,怎么办
1、先找子类中,有没有这个方法,如果有,就调用
2、如果子类中没有该方法,就去父类中查找,如果有,就调用
3、如果都没有,就报错

生活里面的案例:杯子——保温杯——保冷杯

代码举例:

class OldPhone{
    public void call(String name){
        System.out.println("给"+name+"打电话");
    }
}

class NewPhone extends OldPhone{
    public void call(String name){
        super.call(name);
        System.out.println("玩手机");
    }
}

public class ExtendsDemo9 {
    public static void main(String[] args) {
        NewPhone newPhone = new NewPhone();
        newPhone.call("hb");
    }
}
//给hb打电话
//玩手机

方法重写的注意事项:
1、父类的私有方法不能被重写
2、子类重写父类方法时,访问权限不能低
要么子类重写的方法比父类的权限高,要么一样
3、父类的静态方法,子类也必须通过静态方法进行重写(其实算不上重写)

class OldPhone1{
    void call(String name){
        System.out.println("打电话给:"+name);
    }

    public static void play(){
        System.out.println("玩初级游戏");
    }
}

class NewPhone1 extends OldPhone1 {
    public void call(String name) {
        super.call(name);
        System.out.println("玩手机");
    }

    public static void play() {
        OldPhone1.play();
        System.out.println("玩进阶游戏");
    }
}

public class ExtendsDemo10 {
    public static void main(String[] args) {
        NewPhone1 newPhone1 = new NewPhone1();
        newPhone1.call("hb");
    }
}
//打电话给:hb
//玩手机

感谢阅读,我是啊帅和和,一位大数据专业即将大四学生,祝你快乐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊帅和和。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值