Java语言知识大盘点(期末总复习)三

简介: Java语言知识大盘点(期末总复习)三
🌹作者:云小逸
📝个人主页: 云小逸的主页
📝Github: 云小逸的Github
🤟motto:要敢于一个人默默的面对自己, ==强大自己才是核心==。不要等到什么都没有了,才下定决心去做。种一颗树,最好的时间是十年前,其次就是现在!学会自己和解,与过去和解,努力爱自己。==希望春天来之前,我们一起面朝大海,春暖花开!==🤟
👏专栏:C++👏 👏专栏:Java语言👏
👏专栏:C语言初阶👏👏专栏:数据结构👏

前言

今天这篇文章主要讲述Java语言的三大特征:继承、封装、多态。
——————————————————————————————
首先先摘抄上几句话:献给坚持创作的我和点开这篇文章希望进步的你:
1.一旦你出现明天开始努力的想法,而不是从现在开始,那明天的你大概率还是虚度光阴。

2.真正让你成长的,永远是那些让你害怕,逃避,疼痛的事情。

3.我们对年龄的恐惧,其实并不在于年龄增长所来的苍老。而是恐惧随着年龄的增长,我们仍然一无所得。

4.你不跳出舒适区,把薪酬都用在吃喝玩乐的陷阱里,日复一日地随波逐流,突破口只会离你越来越远。

5.以前我觉得成绩不重要。清华、北大、复旦、交大°,只能代表学生时代的成就。后来我发现,努力是种习惯,它会贯穿终生。


1.继承

a.继承概述:

(1)什么是继承?

Java允许一个类通过==extends==与另一个类建立父子关系,这就是继承

(2)继承的格式:

子类 extends父类

public class Student extends People {}

Student称为子类(派生类),People称为父类(基类 或超类)。

(3)继承后子类的特点?

子类继承父类,子类可以得到父类的属性和行为,子类可以使用。
Java中子类更强大

(4)继承的核心优点:

提高代码的复用性,多个子类的相同代码可以放在父类中,增强了类的扩展性。

b.继承的设计规范、内存运行原理

设计规范:子类共用属性和行为放在父类,==子类独有属性和行为==放在子类自己那里。

c.继承的特点

1.子类可以继承父类的属性和行为,但是子类不能继承==父类的构造器==。

类有自己的构造器,父类构造器用于==初始化父类对象==。

2.子类可以继承父类私有成员吗?

==有争议的==.
通常意义上说Java的子类不能继承父类的private变量。因为不能直接的访问父类的private变量.但是当你实例化子类时,在内存中有一个父类的私有变量已经放到了内存中。这一点通过子类访问父类的public或protect方法可以访问到父类的私有变量。

3.子类可以直接用子类名访问父类静态成员。那么子类继承了父类静态成员吗??

==有争议的知识点==。
子类可以直接使用父类的静态成员(共享)
但个人认为:==子类不能继承父类的静态成员。(共享并非继承)==

4.Java是单继承模式:一个类只能继承一个直接父类。

单继承:子类只能继承一个直接父类
不支持多继承:子类不能同时继承多个父类

public class 子类C extends 父类A , 父类B{
    public static void main(String[] args) {
              子类 z = new 子类();
               z.method();   // 复习啥?出现二义性
                     //听哪个爸爸的呢?java懵了!因此不支持多继承
    }
}

5.Java不支持多继承、但是支持多层继承。

子类 A 继承父类 B ,父类B 可以 继承父类 C
在这里插入图片描述

6.Java中所有的类都是Object类的子类。

Java中所有类,要么直接继承了Object , 要么默认继承了Object , 要么间接继承了Object, Object是祖宗类。
在这里插入图片描述

d.继承后:成员变量、成员方法的访问特点

(1)就近原则

先子类局部范围找
然后子类成员范围找
然后父类成员范围找,如果父类范围还没有找到则报错。

(2)如果子父类中,出现了重名的成员,会优先使用子类的,此时如果一定要在子类中使用父类的怎么办?

this.子类自己的成员变量
super.父类成员变量/父类成员方法
格式:super.父类成员变量/父类成员方法

e.继承后:方法重写

(1)概念:

子类重写了一个申明==与父类一样的方法==,==覆盖==父类的方法。子类认为父类的该方法不好用,以后用自己重写的方法。

(2)重写方法建议加上一个重写校验注解:@Override

作用1:要求必须是正确重写的才不报错
作用2:可读性好

(3)方法重写注意事项和要求:

1.重写方法的==名称和形参列表==必须与父类被重写方法的名称和形参列表一致
2.私有方法不能重写
3.静态方法不能重写
4.重写方法的权限 >= 被重写方法的访问权限。

f.继承后:子类构造器的特点

特点:

子类的全部构造器默认都会先访问父类的无参数构造器,再执行自己的构造器

为什么?

子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据。
子类初始化之前,一定要调用父类构造器先完成父类数据空间的初始化。
简要理解:
先有爸爸才有儿子。 先调用它爸爸的构造器初始化父类的数据,再调用自己的构造器初始化自己的数据。

代码层面:

默认子类构造器的第一行都有一个super() 访问父类的无参数构造器,写不写都有

g.继承后:子类构造器访问父类有参构造器

(1)super调用父类有参数构造器的作用:

初始化继承自父类的数据。

(2)如果父类中没有无参数构造器,只有有参构造器,会出现什么现象呢?

会报错。因为子类默认是调用父类无参构造器的。

(3)如何解决?

子类构造器中可以通过书写 super(…),手动调用父类的有参数构造器

总结:

调用父类有参数构造器,初始化继承自父类的数据。
super(....) 根据参数调用父类构造器

h.this、super使用总结

this,super的意义:

**this:代表本类对象的引用;super:代表父类存储空间的标识。
this访问子类当前对象的成员。super:在子类方法中指定访问父类的成员。**
在这里插入图片描述

this(...),super(...)的作用:

this(...) : 访问本类兄弟构造器
super(...):在本类构造器中指定访问父类的构造器

注意事项:super(...) 必须放在第一行,this(...) 也必须在第一行。因此2者不能共存一个构造器中。

2.封装

封装的基本思想:

    决定属性和行为归属谁的问题
        定义人类(名称,年龄,吃饭、睡觉)
        定义圆类(半径,画圆)
        定义门类(开门,高宽)
        定义票类(    票价,地址,买票)
        

封装的原则:

对象代表什么,就得封装对应的数据,并提供数据对应的行为。

如何更好的封装呢?

    成员变量建议private私有化,只能本类访问了。
    合理暴露:
        提供成套的getter和setter方法暴露取值和赋值

3.多态:

a.什么是多态?

多态就是同一个行为有很多个表示形态,我们知道三角形是一个形态,四边形也是一个形态,这里的多态其实就是一个端口,多态的出现其实就是对多种端口形态的体现。
更准确的说是:对象的多种形态。

b.多态的前提:

1.有继承关系\实现关系

2.有父类引用指向子类对象。

Fu f=new Zi();

有继承关系,子类对象是可以赋值给父类类型的变量。例如Animal是一个动物类型,而Cat是一个猫类型。Cat继承了Animal,Cat对象也是Animal类型,自然可以赋值给父类类型的变量。

c.多态的格式:

父类类型 变量名 = new 子类/实现类构造器;
变量名.方法名();

d. 多态的使用场景

如果没有多态,在下图中register方法只能传递学生对象,其他的Teacher和administrator对象是无法传递给register方法方法的,在这种情况下,只能定义三个不同的register方法分别接收学生,老师和管理员。

在这里插入图片描述

有了多态之后,方法的形参就可以定义为共同的父类Person。

要注意的是:

  • 当一个方法的形参是一个类,我们可以传递这个类所有的子类对象。
  • 当一个方法的形参是一个接口,我们可以传递这个接口所有的实现类对象(后面会学)。
  • 而且多态还可以根据传递的不同对象来调用不同类中的方法。

在这里插入图片描述

代码示例:

父类:
public class Person {
    private String name;
    private int age;

    空参构造
    带全部参数的构造
    get和set方法

    public void show(){
        System.out.println(name + ", " + age);
    }
}

子类1:
public class Administrator extends Person {
    @Override
    public void show() {
        System.out.println("管理员的信息为:" + getName() + ", " + getAge());
    }
}

子类2:
public class Student extends Person{

    @Override
    public void show() {
        System.out.println("学生的信息为:" + getName() + ", " + getAge());
    }
}

子类3:
public class Teacher extends Person{

    @Override
    public void show() {
        System.out.println("老师的信息为:" + getName() + ", " + getAge());
    }
}

测试类:
public class Test {
    public static void main(String[] args) {
        //创建三个对象,并调用register方法

        Student s = new Student();
        s.setName("张三");
        s.setAge(18);


        Teacher t = new Teacher();
        t.setName("王建国");
        t.setAge(30);

        Administrator admin = new Administrator();
        admin.setName("管理员");
        admin.setAge(35);



        register(s);
        register(t);
        register(admin);


    }



    //这个方法既能接收老师,又能接收学生,还能接收管理员
    //只能把参数写成这三个类型的父类
    public static void register(Person p){
        p.show();
    }
}

f.多态的运行特点

**调用成员变量时:编译看左边,运行看左边
调用成员方法时:编译看左边,==运行看右边==**
案例理解:

//创建对象(多态方式)
        //Fu f = new Zi();
        Animal a = new Dog();
        //调用成员变量:编译看左边,运行也看左边
        //编译看左边:javac编译代码的时候,会看左边的父类中有没有这个变量,如果有,编译成功,如果没有编译失败。
        //运行也看左边:java运行代码的时候,实际获取的就是左边父类中成员变量的值
        System.out.println(a.name);//动物

        //调用成员方法:编译看左边,运行看右边
        //编译看左边:javac编译代码的时候,会看左边的父类中有没有这个方法,如果有,编译成功,如果没有编译失败。
        //运行看右边:java运行代码的时候,实际上运行的是子类中的方法。
        a.show();///Dog --- show方法

        //理解:
        //Animal a = new Dog();
        //现在用a去调用变量和方法的呀?是的
        //而a是Animal类型的,所以默认都会从Animal这个类中去找

        //成员变量:在子类的对象中,会把父类的成员变量也继承下的。父:name  子:name
        //成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。

编译的时候都会先看一看==父类==有没有这个成员变量或者成员方法。这也成了多态的弊端

g.多态的优势

方法中,使用父类作为参数,可以接收所有子类对象

  Animal a = new Dog();
        a.eat();

**当想使用其他子类的时候,直接将第一行中的Dog改为其他子类就好了,
其他不需要改变,这个就是多态的优势。**

h.多态的弊端:

不能使用==子类的特有功能==

 //创建对象
        Animal a = new Dog();
        //编译看左边,运行看右边
        a.eat();

        //多态的弊端
        //不能调用子类的特有功能
        //报错的原因?
        //当调用成员方法的时候,编译看左边,运行看右边
        //那么在编译的时候会先检查左边的父类中有没有这个方法,如果没有直接报错。
        //a.lookHome();
        //lookHom()是Dog子类的特有的功能

lookHom()是Dog子类的特有的功能,使用多态后就不可以使用了。

i.引用类型转换

(1)为什么要转型

使用多态后就无法访问子类独有功能了。

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

回顾基本数据类型转换

  • 自动转换: 范围小的赋值给范围大的.自动完成:double d = 5;
  • 强制转换: 范围大的赋值给范围小的,强制转换:int i = (int)3.14

多态的转型分为向上转型(自动转换)与向下转型(强制转换)两种。

(2) 向上转型(自动转换)

  • 向上转型:多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。
    当父类引用指向一个子类对象时,便是向上转型。

使用格式:

父类类型  变量名 = new 子类类型();
如:Animal a = new Cat();

原因是:父类类型相对与子类来说是大范围的类型,Animal是动物类,是父类类型。Cat是猫类,是子类类型。Animal类型的范围当然很大,包含一切动物。所以子类范围小可以直接自动转型给父类类型的变量。

(3) 向下转型(强制转换)

  • 向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
    一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

使用格式:

子类类型 变量名 = (子类类型) 父类变量名;
如:Aniaml a = new Cat();
   Cat c =(Cat) a;  

(4)案例演示

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

转型演示,代码如下:

定义类:

abstract class Animal {  
    abstract void eat();  
}  

class Cat extends Animal {  
    public void eat() {  
        System.out.println("吃鱼");  
    }  
    public void catchMouse() {  
        System.out.println("抓老鼠");  
    }  
}  

class Dog extends Animal {  
    public void eat() {  
        System.out.println("吃骨头");  
    }  
    public void watchHouse() {  
        System.out.println("看家");  
    }  
}

定义测试类:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();                 // 调用的是 Cat 的 eat

        // 向下转型  
        Cat c = (Cat)a;       
        c.catchMouse();         // 调用的是 Cat 的 catchMouse
    }  
}

(5)转型的异常

转型的过程中,一不小心就会遇到这样的问题,请看如下代码:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】
    }  
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。

(6)instanceof关键字

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型 
如果变量属于该数据类型或者其子类类型,返回true。
如果变量不属于该数据类型或者其子类类型,返回false。

所以,转换前,我们最好先做一个判断,代码如下:

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

(7)instanceof新特性

JDK14的时候提出了新特性,把判断和强转合并成了一行

//新特性
//先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d
//如果不是,则不强转,结果直接是false
if(a instanceof Dog d){
    d.lookHome();
}else if(a instanceof Cat c){
    c.catchMouse();
}else{
    System.out.println("没有这个类型,无法转换");
}

(8)强制类型转换能解决什么问题?

Person p=new Student();
Student s = ( Student)p;

**●可以转换成真正的子类类型,从而调用子类独有功能。
●转换类型与真实对象类型不一致会报错
●转换的时候用instanceof关键字进行判断**

最后

十分感谢你可以耐着性子把它读完和我可以坚持写到这里,摘抄几句话,对你,也对我:
1.别把安全感建立在别人身上,那样就等于把自己人生的选择权,交给了别人。

2.要么努力到出类拔萃,要么就懒得乐知天命。最怕你见识打开了,可努力又跟不上,骨子里清高至极,性格上又软弱无比。

3.想要过什么样的生活,就得有什么样的代价。我没有承担那种代价的能力,所以我甘愿选择默默无闻的平凡。有人活得不平凡,而你只是没看到他的代价而已;何况活成那种不平凡,是没有回头路可走的。
——七董年

没有人会关心你付出过多少努力,撑得累不累,摔得痛不痛,他们只会看你最后站在什么位置,然后羡慕或鄙夷。

5.重蹈覆辙的下场就是自取其辱,失而复得的东西根本回不到当初,重读一本书可能会有新的感悟,但不会有新的结局。

最后如果觉得我写的还不错,请不要忘记==点赞==✌,==收藏==✌,加==关注==✌哦(。・ω・。)

愿我们一起加油,奔向更美好的未来,愿我们从懵懵懂懂的一枚==菜鸟==逐渐成为==大佬==。加油,为自己点赞!

注:本篇文章是本人在b站学习黑马程序员的学习笔记,无任何商用用途,仅为自己和读者的Java语言学习的学习资料。

目录
相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
69 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
3月前
|
Java Maven
使用java语言制作一个窗体(弹窗),用来收集用户输入的内容
该博客文章介绍了如何使用Java Swing中的JFrame创建一个窗体来收集用户输入的内容,并提供了详细的实现步骤和完整代码示例。
使用java语言制作一个窗体(弹窗),用来收集用户输入的内容
|
8天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
21 4
|
29天前
|
Java 程序员 编译器
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。
在Java编程中,保留字(如class、int、for等)是具有特定语法意义的预定义词汇,被语言本身占用,不能用作变量名、方法名或类名。本文通过示例详细解析了保留字的定义、作用及与自定义标识符的区别,帮助开发者避免因误用保留字而导致的编译错误,确保代码的正确性和可读性。
42 3
|
1月前
|
移动开发 Java 大数据
深入探索Java语言的核心优势与现代应用实践
【10月更文挑战第10天】深入探索Java语言的核心优势与现代应用实践
49 4
|
1月前
|
存储 Java 数据安全/隐私保护
Java中的域,什么是域?计算机语言中的域是什么?(有代码实例)
文章解释了Java中域的概念,包括实例域、静态域、常量域和局部域,以及它们的特点和使用场景。
49 2
|
1月前
|
Java 数据安全/隐私保护 C++
Java语言关键字
Java语言关键字
21 2
|
1月前
|
分布式计算 安全 Java
Java语言的特点?
Java语言的特点?
|
4月前
|
算法 Java
Java语言实现最短路径算法(Shortest Path)
Java语言实现最短路径算法(Shortest Path)
60 3
|
3月前
|
Rust JavaScript Java
简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能
简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能