Java笔记——08.面向对象(中级)
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)比较
发生范围:本类;父子类
方法名:必须一样;必须一样
形参列表:类型、个数或者顺序至少有一个不同;相同
返回类型:无要求;子类重写的方法,返回的类型和父类返回的类型一致或者是其子类
修饰符:无要求;子类方法不能缩小父类方法的访问权限
多态
方法或对象具有多种形态,是面向对象的第三大特征,多态是建立在封装和继承的基础之上的。
多态的前提是两个对象(类)存在继承关系。
方法的多态:
重写和重载就体现多态
对象的多态(核心):
- 一个对象的编译类型和运行类型可以不一致
- 编译类型在定义对象时,就确定了,不能改变
- 运行类型是可以变化的
- 编译类型看定义时 = 号 的左边,运行类型看 = 号 的右边
//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.面向对象(中级)相关推荐
- Java基础(08) 面向对象
Java基础(八)-- 面向对象 面向对象(Object Oriented Programming, 简称OOP )是Java基础学习的重点,必须掌握每个细节,接下来对面向对象的学习主要围绕以下三 ...
- Java笔记(08):面向对象--抽象类
1.抽象类概述: 1 /* 2 抽象类的概述: 3 动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的. 4 我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须 ...
- Java笔记:面向对象3大特性
三大特性 一.封装 1.基本演示: 2.探究: 3.总结 二.继承 1.实例演示 2.查看继承关系 3.Object 4.surper 5.方法的重写 代码一组: 组二: 组三 重写方法的代码 思考与 ...
- Java笔记--08
IO需要掌握的16个流 FileInputStream FileOutputStream FileReader FileWriter BufferedReader BufferedWriter Buf ...
- Java笔记-08 异常
文章目录 异常 运行时异常RuntimeException 受检异常CheckedException throws 自定义异常 异常 异常指程序运行过程中出现的非正常现象,例如用户输入错误.除数为零. ...
- (韩顺平)08 面向对象编程(中级部分)(自用)
目录 08 面向对象编程(中级部分) 8.1 IDE(集成开发环境)-IDEA 8.1.1IDEA 介绍 8.2 IDE(集成开发环境)-Eclipse 8.2.1Eclipse 介绍 8.3 IDE ...
- JAVA自学笔记08
JAVA自学笔记08 1.构造方法私有,外界就不能再创建对象 2.说明书的制作过程 1)写一个工具类,在同一文件夹下,测试类需要用到工具类,系统将自动编译工具类:工具类的成员方法一般是静态的,因此在测 ...
- 【java】java学习笔记之java oop(面向对象)
如下图所示为笔者总结的java oop(面向对象)学习笔记,其中,附带有代码示例(未展开),方便理解记忆.需要源文件的请到我的资源中下载,下载地址:https://download.csdn.net/ ...
- Java基础——面向对象(中级)
面向对象(中级) 包 基本语法 package 包名; 说明: package是关键字,表示打包. 作用 区分相同名字的类 当类很多时,可以很好的管理类 控制访问范围 本质 实际上就是创建不同的文件夹 ...
- Java笔记-面向对象(上)
面向对象(上) Java是面向对象的程序设计语言,Java语言提供了定义类.成员变量.方法等最基本的功能.类可被认为是一种自定义的数据类型,可以使用类来定义变量,所用使用类定义的变量都是引用变量,它们 ...
最新文章
- 从Google代码库找到的好东西
- 不喜欢SAP GUI?那试试用Eclipse进行ABAP开发吧
- 25个出众的Web表单范例
- 好家伙,MacOS 新版本终于删掉自带 Python2,连 Python 死忠粉都叫好!
- 疯子的算法总结(四)贪心算法
- selenium自动化测试_使用Selenium自动化测试处理多个浏览器选项卡
- 【Python】Matplotlib绘制三维线形图
- Python中if name main的作用
- 微服务开发及部署_基于 Kubernetes 的微服务部署即代码
- TD数量不确定时如何让其宽度平均分布
- java的write无法写入,Java加载ImageIO.write的文件在.jar中不起作用
- SSL常用专业缩略语汇总
- shell for循环命令行_24 道 shell 脚本面试题
- 用几何画板求曲线弧长的方法
- ffmpeg系列之两种视频解码方式
- 建模案例1:北京二手房房价影响因素
- 大数据之足球盘口赔率凯利必发数据采集爬虫
- 网络带宽和质量测试小工具.iPerf3
- Java密码连接redis
- matlab代码:面向全局搜索的自适应领导者樽海鞘群算法
热门文章
- 计算机英语论文1000,1000字的英语论文范文大全
- bigboss help啊
- web前端大作业:诗人文化网页主题网站【唐代诗人】纯HTML+CSS制作
- 揭秘跨境电商亚马逊店铺新手培训骗局!有人已经被骗了好几万了!
- 利用JS模拟排队系统
- discuz 模板标签
- 3.7、PHP命名空间
- VC++6.0共享内存技术总结
- Java Calendar,Date,DateFormat,TimeZone,Locale等时间相关内容的认知和使用(2) 自己封装的Calendar接口
- ES(ElasticSearch) 索引创建