java_day7_继承、final关键字、代码块、多态

一、继承

1、继承

    我想养一只🐕,所以先创建一个Dog类,里面有姓名和年龄的属性,吃饭和睡觉的方法
    我还想养一只🐱,猫也有姓名和年龄,也有吃饭和睡觉的方法,按照之前的做法,我们可以按照Dog类的写法再写一遍Cat类
    若我们还想养其它的动物的话,每个动物都有自己的名字和年龄,以及都会吃饭和睡觉,如果我们每一个类都写一遍的话,
    就会觉得代码重复度非常的高。
    java替我们考虑到了,我们可以使用另外一个A类,将重复的内容放到这个A类中,让B类和C类与A类,产生一个关系,
    关系一旦建立,B类和C类中,也就拥有了A类中的内容。这个关系,就是继承。
    java提供了一个关键字用来表示继承关系:extends
    写法:class B extends A{} 表示B类继承自A类
        这里的B称之为:子类,派生类
        这里的A称之为:父类,基类或者超类

    以后开发功能的时候,提倡高内聚,低耦合。

java中,类与类之间继承的时候,不允许一次继承多个类,只允许单继承,但是可以进行多重继承,形成继承体系

class Mother{

}

class GrandFather{

}

class Father extends GrandFather{

}

class Son extends Father{

}


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

public class ExtendsDemo2 {
    public static void main(String[] args) {

    }
}
    使用继承的注意事项:
        1、子类无法继承父类中私有的成员
        2、子类不能继承父类的构造方法
        3、不要为了部分功能而去继承
    问题:什么时候使用继承的思想,什么时候不用?
      答:当符合英语语法中的 is a的时候,就可以使用
class Animal{
    String name;
    int age;

    public void eat(){
        System.out.println("吃饭");
    }

    public void sleep(){
        System.out.println("睡觉");
    }
}

class Dog extends Animal {
    //子类相当于这里有一份父类中的非私有成员

    public void lookDoor(){
        System.out.println("看家");
    }
}

class Cat extends Animal{

}

public class ExtendsDemo1{
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();
        dog.sleep();
        System.out.println(dog.name);
        System.out.println(dog.age);
    }
}

2、子类寻找成员变量并使用的流程

        1、先就近原则,在方法内部中查找一次,若找到就使用
        2、若方法内部没有需要的变量,去当前类成员变量的位置上查找,若找到就使用
        3、若当前类成员变量的位置上没有需要的变量,去父类中的成员变量的位置上查找,若找到就使用
        4、若上面3个地方都没有找到所需要的变量,就报错

3、super关键字

    java中提供了另外一个关键字super,用法跟this很像,但是super代表的是当前子类的直接父类的引用
    在子类中,可以通过super关键字使用直接父类中的非私有成员
    super关键字的使用注意事项:
        1super仅代表当前类中的直接父类,无法使用super获取父类的父类中的成员
        2super后面不能再调用super
class GrandFu3{
    int a = 10;
}

class Fu3 extends GrandFu3{
     int a = 30;
}

class Son3 extends Fu3{
    int a = 20;
    public void fun1(){
        System.out.println(a);
        System.out.println(super.a);
//        System.out.println(super.super.a);
        GrandFu3 grandFu3 = new GrandFu3();
        System.out.println(grandFu3.a);
    }
}

public class ExtendsDemo5 {
    public static void main(String[] args) {
        Son3 son3 = new Son3();
        son3.fun1();
    }
}

4、继承和构造方法的关系

    
    在java继承关系中,要想初始化子类,必须先初始化其父类,这里默认super()体现的就是这个意思

    1、子类构造方法的第一句话,默认会有一个super(),对父类做初始化,只能在子类构造方法第一句出现。
    问题:如果父类中没有无参构造方法呢?
        1)使用super关键字调用父类中的有参构造方法,完成父类的初始化
        2)调用当前类中其它有参的构造方法间接对父类做初始化
    2、java中每一个只允许初始化一次
class Fu4{
//    Fu4(){
//        System.out.println("这是父类中的无参构造方法.....");
//    }

    Fu4(String s){
        System.out.println("这是父类中有参数的构造方法....");
    }
}

class Son4 extends Fu4{
    Son4(){
        //super()
        super("数加");
//        this("数加");
        System.out.println("这是子类的无参构造方法.....");
//        super("数加");
    }

    Son4(String s){
        super(s);
    }
}

public class ExtendsDemo6 {
    public static void main(String[] args) {
        Son4 son4 = new Son4();
    }
}

5、继承与成员方法的关系

    当子类中的方法声明【方法的返回值类型,方法名和参数列表】与父类中的方法声明一致的时候,只是方法的实现不一样,这个现象叫做方法的重写【方法的覆盖】。
    java提供了一个注解帮助我们判断是否是重写@Override
class Fu5{
    public void fun1(){
        System.out.println("这是父类中的fun1方法");
    }
}

class Zi5 extends Fu5{

    @Override
    public void fun1(){
        System.out.println("这是子类中的fun1方法");
    }


    public void fun2(){
        System.out.println("这是子类中的fun2方法");
    }
}

public class ExtendsDemo7 {
    public static void main(String[] args) {
        Zi5 zi5 = new Zi5();
        zi5.fun2();
        zi5.fun1();
    }
}

6、重写所需要注意事项

        1、子类无法重写父类中的私有方法
        2、子类无法继承且重写父类中的静态方法
        3、子类重写方法的权限,要大于等于父类的方法权限,推荐在没有要求的情况下,保持和父亲一致的权限就好了

    面试题:重写和重载什么区别?【overload和override什么区别?】
        1、重写是发生在继承关系中的,指的是子类方法的返回值类型和方法名以及参数列表与父类方法一致,只是实现不一样
        2、重载是发生在同一个类中,值的是方法名一样,参数列表不同,与返回值无关的现象

二、final关键字

    java提供了以关键字给我们使用,可以修饰父类成员方法,让其只能被子类使用,不能重写。
    final: 最终的,不可改变的
    final的用法:可以修饰类,变量,方法
        类:若修饰类,该类不能被继承
        变量:修饰变量,变量变常量,不能修改被final变量的值,自定义常量
        方法:若修饰方法,方法不能被子类重写

被final所修饰的成员变量,必须要在构造方法结束之前给值

class Fu8 {
    final int a = 10;
    int b = 10;

}
class Zi8 extends Fu8 {
    public void fun1(){
//        a = 20;
        System.out.println(a);
    }
}
public class FinalDemo1 {
    public static void main(String[] args) {
//        Zi8 zi8 = new Zi8();
//        zi8.fun1();

        final Fu8 f = new Fu8(); // 指的是地址值不能被修改
        System.out.println(f.a);
        System.out.println(f.b);
//        f.a = 100;
        f.b = 100;
        System.out.println(f.b);

//        f = new Fu8();
    }
}

三、代码块

    代码块:在java程序中,使用{}括起来的代码,代码块

    在不同的位置,以及使用不同的修饰词写的代码块,分为不同种类的代码块。
    局部代码块:在方法中使用带括号括起来的代码段,整体称之为叫做局部代码块,主要作用是限定变量的作用域
    构造代码块:写法和局部代码块的写法是一样的,但是构造代码块是写在类中方法外的位置
        随着构造方法的调用而执行,执行顺序是 构造代码块->构造方法
    静态代码块:写法上在前两种代码块的写法上,前面是使用static进行修饰,在类中方法外编写
        是在程序运行之前,加载的时候执行,只会加载一次,静态代码块只会在程序运行之前有且仅执行一次!
        同一个类中静态代码块之间的执行顺序是自上而下
        静态代码块 -> 构造代码块 -> 构造方法
public class CodeDemo1 {

    CodeDemo1(){
        System.out.println("这是无参的构造方法。。。。");
    }

    //静态代码块
    static {
        System.out.println("这是静态代码块1。。");
    }

    //构造代码块
    {
        System.out.println("这是构造代码块。。。");
    }

    //静态代码块
    static {
        System.out.println("这是静态代码块2。。。");
    }

    public static void main(String[] args) {
//        {
//            //局部代码块
//            int a = 10;
//            System.out.println(a);
//        }
//
//        {
//            //局部代码块
//            int a = 20;
//            System.out.println(a);
//        }

        CodeDemo1 codeDemo1 = new CodeDemo1();
        CodeDemo1 codeDemo2 = new CodeDemo1();


    }
}

四、多态

1、多态

多态:指的是某一个事物,在不同时刻下的不同状态
举例:水【气态的水,液态的水,固态的水】
    水果【🍉,🍇,🍎】

2、java实现多态有三要素

java实现多态有三要素:
    1、要有继承关系
    2、要有方法的重写
        子类可以不重写父类中的方法,但是重写了会更好的体现子类的特点
    3、要有父类的引用指向子类对象
class Animal2{
    String name;
    int age;

    public void eat(){
        System.out.println("吃");
    }

    public void sleep(){
        System.out.println("睡");
    }
}

class Dog2 extends Animal2{
    @Override
    public void eat(){
        System.out.println("🐕吃🥩");
    }

    @Override
    public void sleep(){
        System.out.println("🐕侧着睡");
    }
}

class Cat2 extends Animal2{
    @Override
    public void eat(){
        System.out.println("🐱吃🐟");
    }

    @Override
    public void sleep(){
        System.out.println("🐱蜷着睡");
    }
}


public class DuoTaiDemo1 {
    public static void main(String[] args) {
        //要有父类的引用指向子类对象
        Animal2 a1 = new Dog2(); // 类与类之间的多态

//        Dog2 d1 = new Cat2();
    }
}

3、多态访问成员的特点

    多态访问成员的特点:
        成员变量:编译看左,运行看左。
        成员方法:编译看左,运行看右。
        静态成员方法:编译看左,运行看左。
class Fu10 {
    int a = 10;

    public void fun1() {
        System.out.println("好好学习,天天向上!");
    }

    public static void show1() {
        System.out.println("这是父类中的静态方法show1");
    }

}

class Zi10 extends Fu10 {
    int a = 20;

    @Override
    public void fun1() {
        System.out.println("在数加科技里好好学习!");
    }

    //    public void fun1() {
//        System.out.println("在数加科技里好好学习!");
//    }

    public static void show1() {
        System.out.println("这是子类中的静态方法show1");
    }
}

public class DuoTaiDemo2 {
    public static void main(String[] args) {
        Fu10 f = new Zi10();
        System.out.println(f.a);
        f.fun1();
        f.show1();
    }
}
posted @   w我自横刀向天笑  阅读(55)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示