面向对象(中)

继承性(inheritance)

继承性的好处:why?

  • 减少了代码的冗余,提高了代码的复用性
  • 便于功能的扩展
  • 为之后类多态性提供了前提

继承性的格式:class A extends B{}
A:子类、派生类、subclass
B:父类、超类、基类、superclass
体现:一旦子类A继承父类B之后,之类A中就获取了父类B中声明的所有属性和方法,特别的,父类中声明为private的属性或方法,子类继承父类之后,仍然认为获取了父类中私有的结构。只是因为封装性的影响,使得子类不能直接调用父类的结构而已
子类继承父类之后,还可以声明自己特有的属性或方法:实现功能的扩展。
extends:延展、扩展

java关于继承性的规定:

  1. 一个类可以被多个子类继承
  2. 一个类只能有一个父类,Java中类的单继承性
  3. 子父类是相对的的概念。
  4. 子类直接继承的父类,称为直接父类。间接继承的父类称为:间接父类
  5. 子类继承父类就获取了直接父类以及所有间接父类中声明的属性和方法

如果我们没有显式的声明一个一个类的父类的话,则此类继承于java.lang.Object类。所有的java类出Object类都直接或者间接继承于java.lang.Object类。意味着,所有的java类具有java.lang.Object类声明的功能。

方法的重写(override/overwrite)

  • 定义: 在子类中可以根据需要对从子类中继承来的方法进行改造,也叫做方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
  • 要求:
  1. 子类重写的方法必须和父类被重写的方法具有相同的方法名称、参数列表
  2. 子类重写的方法的返回值类型不能大于父类被重写的方法的返回值类型,父类被重写的方法的返回值类型时A类型,则子类重写的方法的返回值类型可以是A类或者时A类的子类。父类被重写的方法的返回值类型时void,则子类重写的方法的返回值类型也为void。父类被重写的方法的返回值类型时基本数据类型(double),则子类重写的方法的返回值类型必须时相同的基本数据类型(也必须是double)
  3. 子类重写的方法使用权限不能小于父类被重写的方法的访问权限,子类不能重写父类中声明的private权限的方法
  4. 子类方法抛出的异常不能大于父类被重写方法的异常
  • 注意:
    子类与父类中同名同参数的方法必须同时声明非static的(即为重写),或者同时声明为static的(不重写)。因为static方法时属于类的,子类无法覆盖父类的方法

四种不同的权限修饰符

修饰符 类内部 同一个包 不同包的子类 同一个工程
private Yes
default(缺省) Yes Yes
protected Yes Yes Yes
public Yes Yes Yes Yes

super关键字

  1. super理解为:父类的
  2. super可以用来调用属性、方法、构造器
  3. super的使用
    • 我们可以在子类的方法或构造器中,通过使用“super.属性"或”super.方法"的方式,显示的调用子类中声明的属性或方法 但是,通常情况下,我们习惯省略"super."
    • 特殊情况:当子类和父类中定义了同名的属性时,我们想在子类中调用父类中声明的属性,则必须显式的使用"super.属性"的方式,表命调用的是父类中声明的属性
    • 特殊情况:当子类重写了父类中的方法以后,我们想在子类的方法中调用父类中被重写的方法时,则必须显示的使用"super.方法"的方式,表命嗲用的是父类中被重写的方法
  4. super调用构造器
    • 我们可以在子类的构造器中显示的使用"super(形参列表)"的方式,调用父类中声明的指定的构造器
    • "super(形参列表)"的使用,必须声明在子类构造器的首行!
    • 我们在类的构造器中,针对于"this.(形参列表)"或"super(形参列表)"只能二选一,不能同时出现
    • 在构造器的首行,没有显示的声明"this(形参列表)"或"super(形参列表)",则默认调用的是父类中空参的构造器:super()
    • 在类的多个构造器中,至少有一个类的构造器中使用了"super(形参列表)",调用父类中的构造器

子类对象实例化的全过程

  1. 从结果上来看,子类继承父类之后,就获取了父类中声明的属性或方法.创建子类对象,在堆空间中,就会加载所有父类中声明的属性
  2. 从过程上来看:当我们通过子类的构造器创建子类对象时,我们一定会直接或间接的调用其父类的构造器,进而调用父类的父类构造器,直到调用了java.lang.Object类中空参的构造器为止.正因为加载过所有父类的结构,所以才可以看到内存中有父类中的结构,子类对象才可以考虑进行调用.

明确: 虽然创建子类对象时,调用了子类的构造器,但是自始至终就创建一个对象,即为new的子类对象

多态性

  • 多态性,时面向对象中最重要的概念,在java中体现:
    对象的多态性:父类的引用指向子类的对象
    可以直接应用在抽象类和接口上

  • java引用变量有两个类型:编译时类型和运行时类型.编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定.简称:编译时,看左边;运行时,看右边.
    若编译时类型和运行时类型不一致,就出现了对象的多态性(Polymorphism)
    多态情况下,"看左边":看的是父类的引用(父类中不具备父类持有的方法)
    "看右边":看的是子类的对象(实际运行的是子类重写父类的方法)

  • 多态的使用:当调用子父类同名同参数的方法时,实际执行的是子类重写父类的方法,不能调用子类特有的方法---虚拟方法调用,

  • 多态性的使用前提:1.类的继承关系 2. 方法的重写

  • 对象的多态性,只适用于方法,不适用于属性(编译和运行都看左边)

instanceof 操作符

有了对象的多态性以后,内存中实际上是加载了子类特有的属性和方法的,但是由于变量声明为父类类型,导致编译时,只能调用父类中声明的属性和方法.子类特有的属性和方法不能调用

如何才能调用子类特有的属性和方法? 使用强制类型转换(向下转型)

自动类型提示:小->大 如(int 转为 double)
强制类型转换:大->小 如(double转为 int)

向下转型:父类到子类(使用instanceof进行判断)
向上转型(多态):子类到父类

使用强转时,可能出现ClassCastException的异常,需要使用instanceof
a instance of A :判断对象a是否是类A的实例.如果是返回true;如果不是,返回false

如果a instanceof A 返回true,则a instanceof B 也返回true 其中类B是类A的父类

注意:
1.若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中,编译看左边,运行看右边
2.对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量,编译运行都看左边

java.lang.Object类

  1. Object类是所有Java类的根父类
  2. 如果在类的声明中未使用extends关键字指明其父类,则默认父类为java.lang.Object类
  3. Object类中的功能(属性、方法)就具有通用性
    属性:无
    方法:equals()/toString()
    equals():(对比==)
    ==:运算符,可以使用在基本数据类型变量和引用数据类型变量中
    如果比较的是基本类型变量:比较两个变量保存的数据是否相等,类型不一定相等
    如果比较的是引用类型变量:比较两个对象的地址值是否相等,即两个引用是否指向同一个对象实体
    equals()方法的使用:是一个方法,而非运算符,只适用于引用数据类型。Object中equals()的定义和==的作用是相同的,是比较两个对象的地址是否相同,像String、Date、File、包装类等都重写了equals()的方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的实体内容是否相同。如果我们想要比较两个对象的实体内容是否相同,则要对equals()进行重写
    toString():
    1.当我们输出一个对象的引用时,实际上就是调用当前对象的toString() 2.Object类中toString()的定义:获取对象的类的名称+@+哈希code值 3.像String,Date,File,包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()时,返回"实体内容"信息 4.自定义类也可以重写toString()方法,当调用此方法时,返回对象的“实体内容”
  4. Object类只声明了一个空参构造器
  5. finalize是垃圾回收后会调用的一个函数,一般我们不要去主动调这个方法

包装类(wrapper)的使用

针对八种基本数据类型定义相应的引用类型---包装类(封装类)
有了类的特点,就可以调用类中的方法,java 才是真正的面向对象
数值型的都继承自Number
包装类的使用:
1.Java提供了8中基本数据类型的包装类,使得基本数据类型的变量具有类的特征
2.掌握的:基本数据类型、包装类、String三者之间的相互转换
基本数据类型---->包装类:调用包装类的构造器
包装类---->基本数据类型:调用包装类的xxxValue()
新特性:自动装箱与拆箱:
自动装箱:
int num =10;
Integer number = num;
自动拆箱:
System.out.pringln(number.toString());
int num1 = number;

基本数据类型、包装类--->String类型
方式1:连接用酸+""
方式2:调用String重载的valueOf(Xxx xxx);

String类型--->基本数据类型、包装类
调用包装类的parseXxx()

面试题:
Object o1 = true ? new Integer(1) :new Double(2.0)
System.out.println(o1);//1.0

//Integer内部定义了IntegerCache结构,IntegerCache中定义了Integer[],//保存了从-128~127范围的整数。如果我们使用自动装箱的方式,给Integer赋值的范围在//-128~127范围内时,可以直接使用数组中的元素,不用再去new了。目的:提高效率

posted @   生活的样子就该是那样  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示