JavaSE学习之--继承和多态(二)

简介: JavaSE学习之--继承和多态(二)

JavaSE学习之--继承和多态(一)+https://developer.aliyun.com/article/1413489

5.再谈初始化

 先回顾一下静态代码块,实例代码块,构造方法之间执行的先后顺序!

class Test {
    int a;
    // 构造方法
    public Test() {
        System.out.println("这是构造方法!!!");
    }
    // 静态块
    static {
        System.out.println("这是静态代码块!!!");
    }
    // 实例代码块
    {
        System.out.println("这是实例代码块!!!");
    }
}
public class Test1 {
    public static void main(String[] args) {
        Test test1 = new Test();
        System.out.println("=============");
        Test test2= new Test();
    }
}

执行结果:

总结:执行顺序-->静态代码块-->实例代码块-->构造方法

且静态代码块只会被执行一次

那如果既有父类的代码块和构造方法,又有子类的代码块和构造方法,执行顺序是怎样的呢?

先看代码:

class Test {
    int a;
    // 父类的构造方法
    public Test() {
        System.out.println("这是构造方法!!!");
    }
    // 父类的静态块
    static {
        System.out.println("这是静态代码块!!!");
    }
    // 父类的实例代码块
    {
        System.out.println("这是实例代码块!!!");
    }
}
class DTest extends Test {
    // 子类的构造方法
    public DTest() {
        System.out.println("这是子类的构造方法!!!");
    }
    // 子类的静态代码块
    static {
        System.out.println("这是子类的静态代码块!!!");
    }
    // 子类的代码块
    {
        System.out.println("这是子类的代码块!!!");
    }
}
public class Test1 {
    public static void main(String[] args) {
        DTest test1 = new DTest();
        System.out.println("=============");
        DTest test2= new DTest();
    }
}

执行结果:

执行顺序:

1.父类,子类的静态代码块

2.父类实例代码块,构造方法

3.子类的实例代码块,构造方法

所有的静态代码块无论实例化多少个对象都只会被执行一次!!!

6.protected关键字

 为了实现封装特性,引入了访问修饰限定符,不同的关键字有不同的权限

 protected是“受保护的”,它的权限是可以在同包不同类访问,也可以在不同包但是此包的类是另一个包中类的子类,也就是两个包之间的类存在继承关系!

1.同一个包不同类中成员的访问

class B {
    private int a;
    int b;
    protected int c;
    public int d;
}
class C extends B {
    // 同一个包不同类
    public void method() {
        super.a = 20;// err,private成员不能跨类访问
        super.b = 20;// 默认权限的成员可以跨类访问
        super.c = 20;// protected成员可以跨类访问
        super.d = 20;// public成员可以跨类访问
    }
}

2.不同包不同类中成员的访问

class B {
    private int a;
    int b;
    protected int c;
    public int d;
}
// 不同包但存在继承关系之间成员的访问
class C extends B {
    public void method2() {
        super.a = 20;// err private成员不能跨类访问
        super.b = 20;// err 默认权限成员不能跨包访问
        super.c = 20;// protected成员在子类中可以访问
        super.d = 20;// public成员可以跨包访问
    }
}

注意不要忘记引入父类的包:

总结:

1.继承是可以跨包的,如果另一个包中类是另一个包中的类的子类,则存在继承关系;子类会继承父类所有的成员和方法(但是不能全部访问,这取决于父类中成员或方法的访问权限)

2.我们有这么多的权限,那什么时候用什么权限呢?前期学习,大家都会使用一种粗暴的方法,把所有的成员设置为private,所有的方法设置为public,在前期对权限理解不深的时候我们可以这样设置,但使用哪个权限还是要具体问题具体分析,这取决于你对成员或方法的需求!

7.Java中的继承关系(三种)

8.final关键字

 final关键字可以修饰变量,方法,类

1.修饰变量会使变量不能被修改(成为常量)

final int b = 20;
        b = 30;// err b是常量,无法修改常量的值

2.修饰类,代表此类无法被继承

final class B {
    private int a;
    int b;
    protected int c;
    public int d;
}
// 此时B就无法被继承
class C extends B {
}

平常我们使用的String类就是被final修饰的

3.修饰方法,此方法无法被重写

9.继承与组合

 继承反映的是类与类之间的关系,同样的,组合 也是一种反应类与类关系的一种思想!

它代表一个类可以由多个类组成,比如一个Person类可以由Leg,Nose,Head类组成,不同于继承的是组合并没有关键字,只需在类中包含其他类就可以实现类的组合,请看下面代码:

class Nose{};
class Head{};
class Leg{};
class Person{
    private Nose nose;// 可以复用Nose类中的方法和属性
    private Head head;// 可以复用Head类中的方法和属性
    private Leg leg;// 可以复用Leg类中的方法和属性
}
class Stu extends Person{
    // 继承了人的鼻子,头,腿
};

二.多态

多态就是通过父类引用不同对象,调用同一个重写的方法时,所表现的行为不同(所产生的结果不同),这种现象就叫做多态!

要理解多态,需要理解几个基本概念:向上转型,重写,向下转型,动态绑定

1.向上转型

1.向上转型的定义:

   父类引用引用子类对象就叫做向上转型(子类对象被父类引用)

class Animal{};
class Dog extends Animal{};
class Cat extends Animal{};
public class Test {
    public static void main(String[] args) {
        // 向上转型
        Animal animal1 = new Dog();
        Animal animal2 = new Cat();

2.实现向上转型的三种方式

1.直接赋值

2.方法传参

3.方法返回

1.直接赋值
Animal animal1 = new Dog();
        Animal animal2 = new Cat();
2.方法传参

   将方法形参设置为父类引用,实参是子类对象,通过调用方法实现将父类引用指向子类对象!

class Animal{
    public void makeSound() {
        System.out.println("动物发出叫声!");
    }
};
class Dog extends Animal{
    @Override
    public void makeSound() {
        System.out.println("小狗在汪汪叫!");
    }
};
//class Cat extends Animal{};
public class Test {
    public static void animalMakeSound(Animal animal) {
        animal.makeSound();
    }
    public static void main(String[] args) {
        Animal mydog = new Dog();
        animalMakeSound(mydog);
    }

       在main方法中我们创建了一个Dog对象,并将其向上转型为Animal类型,接着在animalMakeSound方法中调用该对象,让父类引用指向该对象,在方法内部实现了向上转型!

   通过上述代码我们可以看出,将形参设置为父类引用最大的好处就是增加了代码的通用性!因为实参可以是任意子类对象

JavaSE学习之--继承和多态(三)+https://developer.aliyun.com/article/1413491

目录
相关文章
|
存储 SQL 缓存
使用索引注意合理的数量
【6月更文挑战第9天】本文介绍数据库索引是提升数据检索速度的数据结构,通过减少磁盘访问提高性能。建议根据表的大小和使用频率谨慎创建索引,如核心表不超过7个索引,普通表不超过5个,小型表不超过3个。
321 3
使用索引注意合理的数量
|
测试技术 PHP
大屏幕互动系统PHP源码 附动态背景图和配乐素材 含搭建教程
最新大屏幕互动系统PHP源码 附动态背景图和配乐素材 含搭建教程
255 0
|
存储 JavaScript 前端开发
使用Strve.js来搭建一款 Markdown 编辑器
今天,我们来使用Strve.js来搭建一款 Markdown 编辑器,没错!你没听错。我们需要创建了一个实时 Markdown 编辑器,用户可以在 textarea 中输入 Markdown 文本,然后实时显示转换后的 HTML。你可能会说使用 Strve.js 开发会不会写的特别复杂难懂啊,还不如用 Vue.js 呢!
|
IDE 测试技术 开发工具
Python接口自动化测试框架(基础篇)-- 讨厌的异常处理
本文详细讨论了Python中的异常处理机制,包括异常捕获、异常抛出、自定义异常、环境清理,以及使用上下文管理器确保资源正确释放,最后还提到了Python的标准异常类。
107 1
PTA-二维数组中每行最大值和每行和
该代码段读取一个3x3二维数组的输入,计算每行的最大值和元素和,并按照指定格式输出。给定输入示例为`3 6 5 9 8 2 1 4 5`,输出格式化后的结果为: ``` 3 6 5 6 14 9 8 2 9 19 1 4 5 5 10 ``` 代码首先使用`map(int, input().split())`将输入转换为整数列表,然后通过循环处理每行,计算每行的最大值(`max(s)`)和元素和(`sum(s)`),并使用`f-string`格式化输出,每个数据占4列。
191 1
|
Dart 开发者
Flutter笔记 - 关于 fit 属性以及相关知识的总结
Flutter笔记 - 关于 fit 属性以及相关知识的总结
492 0
|
存储 druid 关系型数据库
时间序列数据库(TSDB)初识与选择
时间序列数据库(TSDB)初识与选择
230 0
|
Java 调度 C++
VirtualThread Pin的处理总结
VirtualThread Pin的处理总结
167 0
|
Ubuntu 编译器 Linux
百度搜索:蓝易云【Ubuntu18.04系统下配置Clion教程】
现在您已经成功配置了CLion在Ubuntu 18.04系统上进行C/C++开发。开始编写和调试您的代码吧!
143 0
|
JavaScript
Vue Router 中实现在新窗口打开页面
Vue Router 中实现在新窗口打开页面
987 0
Vue Router 中实现在新窗口打开页面