08.面向对象(中级)

常用IDEA快捷键(有部分自行定义)

删除当前行:ctrl+D

复制当前行至下一行:ctrl+Y

补全代码:alt+/

添加注释和取消注释:ctrl+/

导入该行需要的类:alt+enter

快速格式化代码:ctrl+alt+L

快速运行程序:alt+R

生成构造方法:alt+insert

查看一个类的层级关系:ctrl+H

定位到具体的方法:ctrl+B

自动分配变量:alt+enter .var

修饰符

本类 同包 子类 不同包
public
protected
默认
private

封装

小技巧:可以将构造器和setXxx结合,在构造器中调用setXxx方法

继承

  • 子类继承了所有的属性和方法,但是私有属性不能在子类中直接访问,要通过父类提供的公共方法去访问

  • 子类必须调用父类的构造器,完成父类的初始化

  • 当创建子类对象时,不管使用子类的哪个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中用super去指定使用父类的哪个构造器完成对父类的初始化工作,否则编译不会通过

  • 如果希望指定去调用父类的某个构造器,则显示的调用一下:super(参数列表 )

  • super在使用时,需要放在构造器的第一行

  • super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

  • java所有类都是Object类的子类,Object类是所有类的基类

  • 父类构造器的调用不限于直接父类,将一直往上追溯直到Object类(顶级父类)

  • 子类最多只能继承一个父类(指直接继承),即java中是单继承机制

  • 不能滥用继承,子类和父类之间必须满足is-a的逻辑关系

继承本质详解

视频地址:https://www.bilibili.com/video/BV1fh411y7R8?p=294

继承的本质就是建立查找关系

方法重写

  • 子类的方法的参数方法名称要和父类方法的参数、方法名称完全一样

  • 子类方法的返回类型和父类方法的返回类型一样,或者是父类返回类型的子类

  • 子类方法不能缩小父类方法的访问权限(public > protested > 默认 > private)

重载(overload)和重写(override)比较

发生范围:本类;父子类

方法名:必须一样;必须一样

形参列表:类型、个数或者顺序至少有一个不同;相同

返回类型:无要求;子类重写的方法,返回的类型和父类返回的类型一致或者是其子类

修饰符:无要求;子类方法不能缩小父类方法的访问权限

多态

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

多态的前提是两个对象(类)存在继承关系。

  • 方法的多态:

    重写和重载就体现多态

  • 对象的多态(核心):

  1. 一个对象的编译类型和运行类型可以不一致
  2. 编译类型在定义对象时,就确定了,不能改变
  3. 运行类型是可以变化的
  4. 编译类型看定义时 = 号 的左边,运行类型看 = 号 的右边
//Animal类是父类,Dog类和Cat类是子类
Animal animal = new Dog();//animal编译类型是Animal,运行类型是Dog
animal = new Cat();//animal的运行类型变成了Cat,编译类型仍然是Animal//例如Animal中有一个cry方法,Dog类中进行了重写
animal.cry();//因为运行时,执行到该行时,运行类型是Dog,所以cry是Dog中的cry

打个比方,便于理解:披着羊皮的狼

表面上看像一只羊,但实际上他是一只狼。羊就好比是编译类型,而狼是运行类型。编译器看到的是编译类型,真正干活的时候是运行类型。

多态的向上转型

本质:父类引用指向子类对象

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

特点:

  • 编译类型看左边,运行类型看右边
  • 可以调用父类中的所有成员(需遵守访问权限)
  • 不能调用子类中特有成员
  • 最终运行效果看子类的具体实现!!!
//Cat类中有个特有的抓老鼠方法catchMouse(),但是下面的写法不能调用
//因为在编译阶段,能调用哪些成员,是由编译类型来决定的
animal.catchMouse();//会报错

编译的时候是javac来执行的,到了运行阶段是java来执行的,java不关心你的编译类型。(本质上还是一开始的基础,先编译再运行,编译的时候按照编译类型Animal来看,等到运行的时候再按照运行类型Cat来看)

不能理解的,可以看视频地址:https://www.bilibili.com/video/BV1fh411y7R8?p=310

多态的向下转型

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

特点:

  • 只能强转父类的引用,不能强转父类的对象
  • 要求父类的引用必须指向的是当前目标类型的对象
  • 当向下转型后,可以调用子类类型中所有的成员
//cat此时的编译类型和运行类型是什么呢?
Cat cat = (Cat) animal;//编译类型是Cat,运行类型也是Cat
cat.catchMouse();//成功//“要求父类的引用必须指向的是当前目标类型的对象”,怎么理解这句话呢?
//例子
Animal animal = new Dog();
Dog dog = (Dog) animal;//正确
Cat cat = (Cat) animal;//错误
//因为animal本质上就是Dog,所以转成Dog不犯错,但是下面这句话就相当于是把一只狗转换成一只猫
//当然错误,编译时不报错,运行时会报错,会报 类型转换异常

多态注意事项和细节讨论

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

A instanceof B 比较操作符,用于判断对象的运行类型是否为XX类型或XX类型的子类型(A是否是B类型或者是其子类型)

//例如有两个类,Sub类继承Base类,都有count属性
class Base {int count = 10;
}
class Sub extends Base {int count = 20;
}
//在main方法中调用属性,输出的是哪一个呢
Base base = new Sub();
System.out.println(base.count);//输出的是10
//因为count是属性,属性看编译类型,注意和上面方法调用的比较//定义AA类和BB类,BB类继承AA类
class AA {}
class BB extends AA {}
//下面的判断是真还是假
BB bb = new BB();
System.out.println(bb instanceof BB);//true
System.out.println(bb instanceof AA);//true

动态绑定机制

  • 当调用对象方法时,该方法会和该对象的内存地址/运行类型绑定
  • 当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
//父类
class A {public int i = 10;public int sum() {return getI() + 10;}public int sum1() {return i + 10;}public int getI() {return i;}
}//子类
class B extends A {public int i = 20;//    public int sum() {//        return getI() + 20;
//    }//    public int sum1() {//        return i + 20;
//    }public int getI() {return i;}
}//main方法中
//请问输出什么?
A a = new B();
System.out.println(a.sum());//30
System.out.println(a.sum1());//20

解析

  • a.sum():首先因为运行类型是B,所以调用B中的sum()方法,但是B中的sum()方法注释掉了,所以向上找到A中的sum()方法,发现A中的sum()方法可用,于是调用它,然后发现里面又调用了getI()方法,根据动态绑定机制,这个getI()方法调用的是B中的getI()方法,所以最终返回30
  • a.sum1():和a.sum()类似,但由于返回的是i + 10,i是属性,不是方法,所以没有动态绑定机制,于是调用的就是A中的i,所以最终返回20

多态应用

多态数组

//Person是父类,Student和Teacher是它的子类
//Person有属性姓名name和年龄age,Student有特有的属性成绩score,Teacher有特有属性工资sal
//创建多态数组,都是向上转型,父类引用指向子类对象
Person[] persons = new Person[5];
persons[0] = new Person("jack", 20);
persons[1] = new Student("marry", 18, 100);
persons[2] = new Student("smith", 19, 30.1);
persons[3] = new Teacher("scott", 30, 20000);
persons[4] = new Teacher("king", 50, 25000);//如何调用子类特有的方法?
//常用方法:利用instanceof
for(int i = 0; i < persons.length; i++) {//调用公有方法if(persons[i] instanceof Student) {//Student特有方法}else if(persons[i] instanceof Teacher) {//Teacher特有方法}else{//......}
}

多态参数

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

Object类详解

equals方法

==和equals的对比

==是一个比较运算符

  • 既可以判断基本类型,又可以判断引用类型
  • 如果判断基本类型,判断的是值是否相等
  • 如果判断引用类型,判断的是地址值是否相等,即判断是不是同一个对象

equals是Object类中的方法,只能判断引用类型,但经常在子类中会重写equals方法,用来比较对象的值是否相等

强烈建议:使用ctrl+B查看源码,可以理解的更加透彻,查看源码对能力的提升有很大帮助

hashCode方法

  • 提高具有哈希结构的容器的效率
  • 两个引用,如果指向的是同一个对象,则哈希值肯定是一样的
  • 两个引用,如果指向的是不同的对象,则哈希值是不一样的(不绝对)
  • 哈希值主要根据地址来的,但不能完全将哈希值等价于地址
  • 在集合中hashCode如果有需要的话,也会重写

toString方法

  • 默认返回:全类名+@+哈希值的十六进制,子类往往重写toString方法,用于返回对象的属性信息
  • 重写toString方法,打印对象或拼接对象时,都会自动调用该对象的toString方法
  • 当直接输出一个对象时,toString方法会被默认调用
//Object的toString()方法的源码
//getClass().getName() 类的全类名(包名+类名)
//Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());
}//当直接输出一个对象时,toString方法会被默认调用
//比如下面这句话就会默认调用monster.toString()
System.out.println(monster);

finalize方法

  • 当对象被回收时,系统自动调用该对象的finalize方法,子类可以重写该方法,做一些释放资源的操作
  • 什么时候被回收:当某个对象没有任何引用时,jvm就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁该对象前,会先调用finalize方法
  • 垃圾回收机制的调用,是由系统来决定(即有自己的GC算法),也可以通过System.gc()主动触发垃圾回收机制(不一定立刻生效)

注意:对于finalize方法了解即可,因为实际开发中,几乎不会使用。

断点调试

重要提示:在断点调试过程中,是运行状态,是以对象的运行类型来执行的

IntelliJ IDEA断点调试如何查看源码:https://blog.csdn.net/qq_43544021/article/details/120633420?spm=1001.2014.3001.5501

**强烈建议:**可以经常进行断点调试,除了检查错误,更重要的是可以对Java的源码,运行机制等等知识点有更深入的理解(尤其是继承,多态这里,看源码真的很重要),而且不只是系统的源码,也可以看看人家高手大佬的代码,提高自己。

Java笔记——08.面向对象(中级)相关推荐

  1. Java基础(08) 面向对象

    Java基础(八)-- 面向对象 ​ 面向对象(Object Oriented Programming, 简称OOP )是Java基础学习的重点,必须掌握每个细节,接下来对面向对象的学习主要围绕以下三 ...

  2. Java笔记(08):面向对象--抽象类

    1.抽象类概述: 1 /* 2 抽象类的概述: 3 动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的. 4 我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须 ...

  3. Java笔记:面向对象3大特性

    三大特性 一.封装 1.基本演示: 2.探究: 3.总结 二.继承 1.实例演示 2.查看继承关系 3.Object 4.surper 5.方法的重写 代码一组: 组二: 组三 重写方法的代码 思考与 ...

  4. Java笔记--08

    IO需要掌握的16个流 FileInputStream FileOutputStream FileReader FileWriter BufferedReader BufferedWriter Buf ...

  5. Java笔记-08 异常

    文章目录 异常 运行时异常RuntimeException 受检异常CheckedException throws 自定义异常 异常 异常指程序运行过程中出现的非正常现象,例如用户输入错误.除数为零. ...

  6. (韩顺平)08 面向对象编程(中级部分)(自用)

    目录 08 面向对象编程(中级部分) 8.1 IDE(集成开发环境)-IDEA 8.1.1IDEA 介绍 8.2 IDE(集成开发环境)-Eclipse 8.2.1Eclipse 介绍 8.3 IDE ...

  7. JAVA自学笔记08

    JAVA自学笔记08 1.构造方法私有,外界就不能再创建对象 2.说明书的制作过程 1)写一个工具类,在同一文件夹下,测试类需要用到工具类,系统将自动编译工具类:工具类的成员方法一般是静态的,因此在测 ...

  8. 【java】java学习笔记之java oop(面向对象)

    如下图所示为笔者总结的java oop(面向对象)学习笔记,其中,附带有代码示例(未展开),方便理解记忆.需要源文件的请到我的资源中下载,下载地址:https://download.csdn.net/ ...

  9. Java基础——面向对象(中级)

    面向对象(中级) 包 基本语法 package 包名; 说明: package是关键字,表示打包. 作用 区分相同名字的类 当类很多时,可以很好的管理类 控制访问范围 本质 实际上就是创建不同的文件夹 ...

  10. Java笔记-面向对象(上)

    面向对象(上) Java是面向对象的程序设计语言,Java语言提供了定义类.成员变量.方法等最基本的功能.类可被认为是一种自定义的数据类型,可以使用类来定义变量,所用使用类定义的变量都是引用变量,它们 ...

最新文章

  1. 从Google代码库找到的好东西
  2. 不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧
  3. 25个出众的Web表单范例
  4. 好家伙,MacOS 新版本终于删掉自带 Python2,连 Python 死忠粉都叫好!
  5. 疯子的算法总结(四)贪心算法
  6. selenium自动化测试_使用Selenium自动化测试处理多个浏览器选项卡
  7. 【Python】Matplotlib绘制三维线形图
  8. Python中if name main的作用
  9. 微服务开发及部署_基于 Kubernetes 的微服务部署即代码
  10. TD数量不确定时如何让其宽度平均分布
  11. java的write无法写入,Java加载ImageIO.write的文件在.jar中不起作用
  12. SSL常用专业缩略语汇总
  13. shell for循环命令行_24 道 shell 脚本面试题
  14. 用几何画板求曲线弧长的方法
  15. ffmpeg系列之两种视频解码方式
  16. 建模案例1:北京二手房房价影响因素
  17. 大数据之足球盘口赔率凯利必发数据采集爬虫
  18. 网络带宽和质量测试小工具.iPerf3
  19. Java密码连接redis
  20. matlab代码:面向全局搜索的自适应领导者樽海鞘群算法

热门文章

  1. 计算机英语论文1000,1000字的英语论文范文大全
  2. bigboss help啊
  3. web前端大作业:诗人文化网页主题网站【唐代诗人】纯HTML+CSS制作
  4. 揭秘跨境电商亚马逊店铺新手培训骗局!有人已经被骗了好几万了!
  5. 利用JS模拟排队系统
  6. discuz 模板标签
  7. 3.7、PHP命名空间
  8. VC++6.0共享内存技术总结
  9. Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(2) 自己封装的Calendar接口
  10. ES(ElasticSearch) 索引创建