08_面向对象编程(中级)

面向对象编程(中级)

IDEA

IDEA常用快捷键

  • ctrl+D 删除当前行
  • ctrl+alt+向下箭头 复制当前行
  • alt+/ 补全代码
  • ctrl+/ 添加或补全注释
  • alt+enter 导入该行需要的类
  • ctrl+alt+L 快速格式化代码
  • alt+R 快速运行程序
  • alt+Insert 生成构造方法等
  • ctrl+H 查看类的继承关系
  • ctrl+B 将光标放到方法上,输入ctrl+B,可以定位到方法
  • 自动分配变量名,在程序后面加.var

IDEA模板

  • file->settings->editor->Live templates-> 查看有哪些模板快捷键,或者自己添加模板
  • 模板可以高效的完成开发,提高开发效率

  • 包的作用

    • 区分相同名字的类

    • 当类很多时,可以很好的管理类

    • 控制访问范围

  • 包基本语法:

    • package 关键字,如package com.dmm,其中com.dmm为包名
  • 包的本质

    • 实际上就是创建不同的文件夹/目录来保存类文件
      在这里插入图片描述
  • 包的命名

    • 只能包含数字、字母、下划线、小圆点,但不能用数字开头,不能是关键字或保留字
    • 一般是小写字母+小圆点,com.公司名.项目名.业务模块名,如
      • com.sina.crm.user
  • java中常用的包

    • java.lang.* //基本包,默认引入,无需再导入
    • java.util.* //工具包,工具类,如使用Scanner等
    • java.net.* //网络包,用于网络开发
    • java.awt.* //Java的界面开发包,GUI
  • 包的使用细节

    • 建议:需要哪个类就导入哪个类即可,不建议使用*导入该包下的全部类
    • package的作用是声明当前类所在的包,需要放在类和import语句的上面
    • 一个类中最多有一个package
    • import指令放在package下面,类定义语句上面

访问修饰符

java提供四种访问控制修饰符号,用于控制方法和属性的访问权限(范围)

  • 公开级别:用public修饰,对外公开
  • 受保护级别:用protected修饰,对子类和同一个包中的类公开
  • 默认级别:没有修饰符号,对同一个包的类公开
  • 私有级别:用private修饰,只有类本身可以访问,不对外公开
    在这里插入图片描述

使用细节

  • 修饰符可以用来修饰类,类中的属性、成员方法
  • 只有默认和public访问修饰符才能修饰类

封装

  • 面向对象编程的三大特征:封装、继承、多态
  • 封装:把抽象出的数据(属性)和对数据的操作(方法)封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作(方法),才能对数据进行操作
  • 封装的作用:
    • 隐藏实现细节
    • 可以对数据进行验证,保证安全合理

封装三部曲

  • 将属性私有化(private),使得使用者不能直接修改属性

  • 提供一个public set方法,用于对数学进行判断并赋值

    • public void setXxx(类型 参数名){
      	//加入数据验证的业务逻辑
      	属性=参数名;
      }
      
  • 提供一个public get方法,用于获取属性的值

    • public 数据类型 getXxx(){
      	return xx;
      }
      

封装与构造器

若想同时使用构造器和set方法,实现即实现了属性的约束与封装,又能自定义属性的值,可将set方法放入构造器中来实现

在这里插入图片描述

继承

在这里插入图片描述

  • 当多个类存在相同的属性和方法时,可以从这些相同的属性和方法中抽象出父类,在父类中定义这些相同的属性和方法,对于共有的属性和方法,所有子类无需重新定义,只需通过extends关键字来声明父类即可

  • 基本语法:

    • class 子类 extends 父类{
      }
      
    • 子类会自动拥有父类定义的属性和方法

    • 父类又叫超类,基类;子类又叫派生类

使用细节

  • 子类继承了父类所有的方法和属性,父类中非private的方法和属性,子类都可直接访问,而若想访问父类中private属性和方法,必须通过父类提供的公共方法来访问
    在这里插入图片描述

  • 子类必须调用父类的构造器,先完成父类的初始化,再初始化自己的特有属性(通过默认存在的super()语句实现的父类初始化)
    在这里插入图片描述

  • 当创建子类对象时,不管使用子类的哪个有参或无参构造器,默认情况下都会去调用父类的无参构造器,若父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器来完成初始化,否则,编译不会通过
    在这里插入图片描述

  • 可以通过super(形参列表)来指定去调用父类的某个构造器

  • super在使用时,必须放在构造器的第一句

  • 由于super和this关键字都必须放在构造器的第一句,因此两者不可同时出现在同一个构造器中

  • Java中所有的类都是object的子类,换言之,object是所有类的基类

  • 父类构造器的调用不限于直接父类,将一致向上追溯到object类
    在这里插入图片描述

  • 子类最多只能继承一个父类(指直接继承),即Java中是单继承机制
    在这里插入图片描述

  • 不能滥用继承,子类和父类之间必须满足is-a的关系,如cat is a animal,可将cat类继承animal类

继承的本质(重要)

  • 继承的内存布局
    在这里插入图片描述

  • 访问属性的规则

    • 向上查找,就近原则
    • 若在查找的过程中,找到了,但不能访问(访问修饰符为private),则报错
    • 若查找过程中没有找到,则提示方法/属性不存在
      在这里插入图片描述

super

  • super代表父类的引用,用于访问父类的属性、构造器和方法
  • 不能访问父类的private属性
    • super.属性名
  • 不能访问父类的private方法
    • super.方法名(形参列表)
  • 访问父类的构造器
    • super(形参列表)
    • 只能放在构造器的第一句,因此不可和this关键字同时使用
    • 只能出现一句

使用细节

  • 调用父类构造器的好处:分工明确,父类属性由父类初始化,子类属性由子类初始化

  • 当子类中有和父类中的成员/属性/方法重名时,为了访问父类的属性,必须通过super,若子父类之间没有重名,使用super/this/直接访问是一样的效果

  • super的访问不限于直接父类,若多个基类(上级类)都有同名的成员,使用super访问就近原则,同时也要遵循访问权限的相关规则

  • super和this的比较
    在这里插入图片描述

方法重写/覆盖(override)

  • 方法重写就是子类有一个方法,和父类的某个方法的名称、返回类型、形参列表一样,则称该子类的方法覆盖了父类的那个方法

使用细节

方法重写也叫方法覆盖,需要满足以下条件:

  • 子类方法的形参列表,方法名称,要和父类的形参列表和方法名称完全一样
  • 子类方法的返回数据类型应和父类的返回数据类型相同,或者是父类返回类型的子类,如父类的返回数据类型为Object,子类的返回数据类型为String(Object类是所有类的父类)
  • 子类方法不能缩小父类方法的访问权限,可扩大

方法重写和重载对比

在这里插入图片描述

多态

多态即指方法或对象具有多种形态,是面向对象的第三大特征,多态建立在封装和继承基础之上

对象的多态

  • 一个对象的编译类型和运行类型可以不一致
    • Animal animal = new Dog();
    • 其中animal对象的编译类型为Animal,运行类型为Dog
  • 编译类型在定义对象时就确定了,不可改变
  • 运行类型是可以变化的
    • animal = new Cat()
    • 此时编译类型依旧为Animal,运行类型改为Cat

使用细节

多态的前提是:两个对象(类)具有继承关系

多态的向上转型
  • 本质:父类的引用指向了子类的对象

  • 语法:父类类型 引用名 = new 子类类型();

  • 特点:=左边看编译类型,=右边看运行类型

  • 向上转型调用方法的规则如下

    • 可以调用父类的所有成员(需遵守访问权限)

    • 不能调用子类的特有成员(属性和方法),因为在编译阶段,能调用哪些成员,是由编译类型来决定的,和运行类型无关
      在这里插入图片描述

      • 不能调用子类的特有方法catchMouse()
    • 属性看编译,方法看运行,从运行类型(子类)开始查找方法,规与方法调用的规则一致,即向上查找,就近原则

      • 调用animal的eat()方法,为子类eat方法的运行结果
多态的向下转型
  • 语法:子类类型 引用名 = (子类类型)父类引用

  • 要求:父类的引用必须指向的是当前子类类型的对象

    • 正确示例:

      • Animal animal = new Cat();
        Cat cat = (Cat)animal;
        //其中Animal为Cat的父类
        
      • 此时animal和cat都指向统一个Cat对象,仅引用类型不同(Animal和Cat),可访问的成员也不同

    • 错误示例:

      • Animal animal = new Animal();
        Cat cat = (Cat)animal;
        //其中Animal为Cat的父类
        
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lhifkt4U-1687437364349)(.assets/image-20220829223409573.png)]

  • 注意事项:

    • 属性没有重写之说,属性的值看编译类型

      • Base base = new Sub();
        //Base为Sub的父类,Base的count属性值为10,Sub的count属性值为20
        System.out.println(base.count);//输出10
        //若首句改为:
        Sub sub = new Sub();
        System.out.println(sub.count);//则输出20
        
    • instanceof比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型,是返回true,不是返回false

      • AA aa = new AA();//AA为BB的父类
        BB bb = new BB();
        System.out.println(aa instanceof AA);//true
        System.out.println(bb instanceof BB);//true
        AA aa = new BB();
        System.out.println(aa instanceof AA);//true
        System.out.println(aa instanceof BB);//true
        Object object = new Object();
        System.out.println(object instanceof AA);//F
        
Exercise

在这里插入图片描述

动态绑定机制(重要)

  • 当调用对象方法时,该方法会和对象的内存地址/运行类型绑定
  • 而当调用对象属性时没有动态绑定机制,哪里声明,哪里使用

多态数组

  • 数组的定义类型为父类类型,里面保存的元素类型为子类类型

    • Person[] persons = new Person(5);
      persons[0] = new Teacher();
      persons[1] = new Student();
      persons[2] = new Person();
      

多态参数

  • 方法定义的形参类型为父类类型,实参类型允许为子类类型

    • public void feed(Animal animal, Food food){
      	System.out.println("is feeding" + animal + food);
      }
      feed(pig,rice);
      feed(dog,bone);
      

object类详解

equals方法

==和equals方法的对比

  • ==是一个比较运算符
    • 即可判断基本数据类型,也可判断引用数据类型
    • 若判断基本类型,则判断两者的值是否相等,如int i=10;double d=10.0;
    • 若判断引用类型,则判断两者地址是否相等,即判断两者是否为同一个对象
  • equals方法
    • 是Object类中的方法,只能判断引用类型
    • java中所有的类都可以调用equals方法
    • 默认判断的是地址是否相等,Object的子类中往往重写该方法,用于判断引用对象的内容是否相等,如String,Integer重写了该方法

子类重写equals

  • Object的equals默认就是比较引用类型对象存储的地址是否相同,源代码为:
    =

  • Integer的equals源代码:在这里插入图片描述

hashCode方法

返回该对象的哈希码值,该方法用于提高哈希表的性能

hashcode小结

  • 用于提高具有哈希结构的容器的效率
  • 两个引用,若指向的是同一个对象,则哈希值肯定相同
  • 两个引用,若指向不同对象,则哈希值不同
  • 哈希值主要根据地址来计算的,但不能将哈希值完全等价于地址
    • hashCode方法会针对不同对象返回不同整数,一般通过将该对象的内部地址转换为一个整数来实现的

toString方法

返回该对象的字符串表示,默认返回:全类名+@+哈希值的十六进制,Object的子类往往重写toString方法,用于返回对象的属性信息

在这里插入图片描述

  • 全类名是指包名+类名
  • IDEA中可通过alt+insert直接重写toString方法
  • 当直接输出对象时,toString方法被默认调用
    在这里插入图片描述

finalize方法

当垃圾回收器确定不存在对该对象更多引用时,由对象的垃圾回收器调用此方法

  • 当对象被回收时,系统会自动调用该对象的finalize方法,子类可重写该方法,做一些释放资源的操作
  • 何时被回收:当某个对象没有任何引用时,JVM会认为该对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用它的finalize方法
  • 垃圾回收机制的调用是由系统来决定的,有自己的gc算法,也可通过下句来主动出发垃圾回收机制
  • 注:在实际开发中,几乎不会运用finalize方法,更多是为了应付面试

断点调试

  • 断电调试过程中是运行状态,是以对象的运行类型来执行的

    • class A extends B{}
      B b = new A();
      b.xx()//b对象调用xx方法时,实际执行的是A类的xx方法
      
  • 断电调试快捷键

    • F7;跳入方法
    • Alt+shift+F7:强制跳入方法
    • F8:跳过方法,逐行执行代码
    • shift +F8:跳出方法
    • F9:(resume),执行到下一断点

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值