八、Java面向对象编程
Java面向对象
初识面向对象
面向过程 & 面向对象
面向过程思想
- 步骤清晰简单,第一步做什么,第二部做什么...
- 面对过程适合处理一些较为简单的问题
面向对象思想
- 物以类聚,分类的思维模式,思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独思考。最后,才对某个分类下的细节进行面向过程思索。
- 面向对象合适处理复杂的问题,适合处理需要多人协作的问题!
对于描述复杂的事物,为了从宏观上把握、从整体上合理分析,我们需要使用面向对象的思路来分析整个系统。但是,具体到微观操作,仍然需要面向过程的思路去处理。
什么是面向对象
面向对象编程(Object-Oriented Programming,OOP)
面向对象编程的本质是:以类的方式组织代码,以对象的组织(封装)数据
抽象:白话理解就是抽像,把像的的抽取出来,具体的理解还是抽像
三大特征:
- 封装
- 继承
- 多态
从认识论角度考虑是先有对象后有类。对象,是具体是事物,类,是抽象的,是对对象的抽象
从代码运行角度考虑是先有类后有对象。类是对象的模板
这些看不懂没关系,后面慢慢的就会恍然大悟!
回顾方法及加深
一个真正的程序里面只有一个main方法,并不会像我们测试的时候每个类里面都有,我们只是为了方便代码的运行
回顾方法的定义
-
修饰符
- public:公共的,所有人都可以调用这个方法
- static:静态,方便调用 (可选)
-
返回类型
- void:空的:不需要使用return返回一个值(但是可以使用return结束方法)
- 其他类型:需要使用return返回一个值,返回的值的类型要与其相对应
-
break和return的区别
- break:跳出switch语句,和结束整个循环;还有一个continue是结束一次循环
- return:结束当前方法,返回一个结果(可以为空)
-
方法名
- 注意规范即可:见名知意,首字母小写+驼峰原理
-
参数列表
- (参数类型 参数名,...) 可以多个,还有一个 可变参数(参数类型... 参数名)
- 异常抛出
- 疑问 (后面讲解)
回顾方法的调用
-
静态方法
- 静态方法:加static的为静态方法
- 静态方法的调用
-
非静态方法
- 非静态方法:没加static的为非静态方法
- 非静态方法的调用
-
特殊情况 原因:static 是和类一起加载的,这个类存在的时候它就存在,时间片非常早;普通方法是类实例化后才存在的
- 两个普通方法(非静态) 或 两个静态方法:可以直接相互调用,无需实例化
- 两个方法中一个一个为普通方法,一个为静态方法,如果静态方法调用非静态,就要实例化;非静态调用静态无须实例化
-
形参和实参:形式参数和实际参数的类型要对应
- 形式参数:是定义方法时的参数;例如:如下代码的(int a, int b)就是形式参数
- 实际参数:是调用方法传递给方法的参数;例如:如下代码的demo03.add(1, 2);
-
值传递和引用传递
-
值传递引用传递的概念
- 值传递是指在调用方法时将实际参数复制一份传递到方法中,这样在方法中如果对参数进行修改,将不会影响到实际参数。
- 所谓引用传递是指在调用方法时将实际参数的地址传递到方法中,那么在方法中对参数所进行的修改,将影响到实际参数。
-
值传递和引用传递的理解
- 值传递 在方法的调用过程中,实参把它的实际值传递给形参,此传递过程就是将实参的值复制一份传递到方法中,这样如果在方法中对该值(形参的值)进行了操作将不会影响实参的值。因为是直接复制,所以这种方式在传递大量数据时,运行效率会特别低下。
- 引用传递 引用传递弥补了值传递的不足,如果传递的数据量很大,直接复过去的话,会占用大量的内存空间,而引用传递就是将对象的地址值传递过去,方法接收的是原始值的首地址值。在方法的执行过程中,形参和实参的内容相同,指向同一块内存地址,也就是说操作的其实都是源数据,所以方法的执行将会影响到实际对象。
-
java本质还是值传递(为什么这么说:引用传递是里面存的首地址的copy。原来引用变量里的的对象你不能改,但是他指向的堆对象你可以改啊。)
-
结论:
- 值传递,相当于拷贝一份值,对参数的修改不影响原有参数
- 引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象。
-
上面还写了一个class(剧透了内部类的内容(后面会讲)) 一个类里面只能有一个public class 但是能有多个class
- this关键字 (讲到继承的时候再讲)
值传递和引用传递大家肯定觉得很绕,这是因为我们对 对象和从内存分析的理解还不透彻,本章后面后面的内容学完再来看一遍,肯定会恍然大悟!
对象的创建*
类与对象的关系
类是一种抽象的数据类型,它是对某一类事物整体描述/定义,但并不能代表某一个具体的事物
-
如动物、植物、手机、电脑
-
Person类、Pet类、Car类等,这些类都是用来描述/定义某一类具体的事物应该具备的特点和行为
对象是抽象概念的具体实例
- 张三就是人的一个具体实例,张三家里的旺财就是狗的一个具体实例
- 能够体现出特点,展现出功能的是具体的实例,而不是一个抽象的概念
创建与初始化对象
以后我们就不要在每一个类里面都去加上main方法,一个程序只有一个主启动类
一个项目只存在一个main方法
我们新建一个包,先来一个Student类,再来一个Application类,Application类定义一个main方法就好也是唯一的一个入口。
我们再IDEA上面,把Application类列到一边,方便我们随时进行测试,如图下
使用new关键字创建对象
这样我们一个简单的类就定义出来了
Student类就是一个抽象的模板,然后我们通过new关键字,可以创建不一样的具体的实例!
大家现在再品一下这句话:以类的方式组织代码,以对象的组织(封装)数据,是不是恍然大悟!
构造器详解
使用new关键字创建的时候,除了分配内存空间之外,还会给 创建好的对象 进行默认的初始化 以及对类中构造器的调用
Person这个类里面我们没有写方法,但是还是能new一个实例出来,就证明类里面有一些默认的东西
这个对象是怎么来的,为什么能凭空new出来,我们去看这个Person类生成的class文件
我们在IDEA点开项目架构,选择modules,再选择新增一个目录(Add Content Root),选择我们的out目录,找到对应的class文件打开就行(如果没有对应的class文件,在IDEA运行一下文件就会生成) Person.class文件内容如下:
你会发现默认的帮我们加了一个方法,而且这个方法没有返回值,方法名字和类名相同;其实这就是一个构造器。
得出结论:一个类即使什么都不写,它也会存在一个方法
- 类中的构造器也称为构造方法,是在进行创建对象的时候必须调用的。并且构造器有以下两个特点:
- 1、必须和类的名字相同
- 2、必须没有返回类型,也不能写void
在.java文件显示的定义构造器:
那么有人就会问,这个无参构造器能干什么:
构造器总结:
构造器定义需注意:
- 和类名相同
- 没有返回值
构造器的作用:
- 使用new关键字的时候构造器就执行了
- 初始化对象的值
注意点:
- 定义了有参构造之后,如果想要使用无参构造,就必须显示的去定义一个无参构造
- 我们可以重载很多个构造器,使用new实例化一个对象的时候,他会根据你传的参数来判断你调用的是哪个构造器
快捷键:
- 在IDEA中使用 Alt+Insert ,选择Constructor能自动生成构造器,参数能选
构造器必须要掌握
类与对象简单小结
1、类与对象
- 类是一个模板(抽象),对象是一个具体的实例
2、方法
- 定义、调用
3、对象的引用
-
引用类型、基本类型(8)
-
对象是通过引用来操作的
4、属性:也叫字段(Field)、或成员变量
默认初始化:
数字:0、0.0;
char:u0000(转化为int类型输出0);
boolean:false;
引用:null
属性的定义:修饰符 属性类型 属性名 = 属性值;
5、对象的创建和使用
- 必须使用new关键字创造对象、构造器 :Person xiaodi = new Person();
- 对象的属性 xiaodi.name;
- 对象的方法 xiaodi.sleep();
6、类
- 类里面只能写属性和方法
面向对象三大特性
封装
- 该露的露,该藏的藏:比如遥控器,暴露一些开关换台键就行,一些底层的就藏起来。用户不需要全部了解
- 我们程序设计要追求“高内聚,低耦合”。高内聚:就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。
- 封装(数据的隐藏)
- 通常,应禁止直接访问一个对象中数据的实际表示,而应该通过操作接口来访问,这称为信息隐藏
- 记住这句话就够了:属性私有,get\set
听不懂没关系上代码:
总结->封装的意义:
- 1、提高程序安全性,保护数据
- 2、隐藏代码实现细节
- 3、统一接口
- 4、提高了系统的可维护性
作用在什么地方:这就要通过大家平时多写代码去积累经验了,大家现在还只是学会了这样一个操作,不知道什么地方需要使用到,在我们后面的学习中就会经常去写封装这个东西,大家到时候慢慢积累就行。
聊一聊方法重载:比如我们的println,为什么它啥都能输出,就是因为它重载了很多方法,方法的参数定义的不同,实现不同类型的输出;大家可以在IDEA中按住Ctrl键然后点击println进去看一下
继承
-
继承的本质是对某一批类的抽象,从而实现对现实世界更好的建模。
-
extends的意思是“扩展”。子类是父类的扩展。
-
Java中类只有单继承,没有多继承! (可以理解为一个儿子只能有一个爸爸,一个爸爸能有多个儿子)
-
继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合,聚合等
-
继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字extends来表示
-
子类和父类之间,从意义上讲应该具有“is a”的关系。(比如:Wangcai is a dog )
上代码理解:
Person 人 父类
Student 学生 子类
Application 启动方法(测试)
继承小总结:
- 关键字:extends;语法:在类名后面加上:[extends 要继承的类名]
- 子类继承父类所有方法以及公共属性
- 私有属性是不能继承的(但是一般情况下是会通过封装的一些方方法去调用或修改);
Object类
记住一个快捷键Ctrl+H:查看当前继承的继承情况
当我们Person类什么都不写的情况下,new一个Person对象,然后输入person.就能点出一些方法,但是我们什么都没定义这是为什么呢?
- 在Java中,所有的类,都默认直接或者间接继承Object类(如果是间接继承,那么Object就是它的爷爷,因为Java中类只有单继承,没有多继承)
super详解
- this是代表当前类的
- super是代表父类的
父类:Person
子类:Student
启动程序(测试):Application
输出结果:
XiaoDi
小迪
晓迪
Student
Student
Person
想一下如果new子类的时候构造器的执行顺序是怎么样的:
父类:Person
子类:Student
启动程序(测试):Application
输出:
Person无参构造执行了
Student无参构造执行了
也就是说父类的无参构造器先执行了
- 如果说我们要调用自己的有参构造this("xiaodi");,也需要放在第一行,否则报错,也就是说两者在同一个构造器里只能使用一个;这个就是super关键字坑爹的地方
那么假如我的父类里面没有无参构造器:
父类:Person
子类:Student
- 会直接导致子类的无参构造也写不了
但是也不是没有办法,没有无参构造,那你显示的写出调用父类的有参构造就行了:
子类:Student
super小总结:
- 1、super是在子类中调用父类的属性或者方法 例如:super.name; super.print();(只能出现在子类的方法或构造方法中)
- 2、super调用父类的构造方法,必须在子类的构造方法的第一个(是隐藏代码,写不写效果是一样的)
- super调用父类构造 和 this调用本类(子类)有参构造 不能同时在一个构造方法里面使用(也就是说能通过骚操作来解决):
父类:Person
子类:Student
如果要调用子类中的有参构造方法的话,且不影响代码,就能像上面这种方法写:调用子类有参构造的同时还调用了父类的无参构造,以上代码的执行顺序是:1父类无参构造、2age=18、3子类无参构造
super VS this
- 代表的对象不同
- this:本身调用者这个对象
- super:代表父类对象的应用
- 前提:
- this:没有继承也可以使用
- super:只能在继承的条件下才能使用
- 构造方法:
- this():本类的构造
- super():父类的构造
方法重写
静态方法
父类:B
子类:A
启动程序:Application
输出:
A->test()
B->test()
非静态方法
父类:B
子类:A
启动程序:Application
方法重写小总结:
- 首先需要有继承关系,子类重写父类的非静态方法!
特点:
- 1、方法名必须相同
- 2、参数列表必须相同 (重载是当前类的,而且参数列表不相同)
- 3、修饰符:重写时子类的访问控制修饰符不能比父类的范围小(public>protected>default>private)(这个先不要纠结,随着后面的学习再来看这个笔记)
- 抛出的异常;范围可以被缩小,但不能扩大;(后面再去了解)ClassNotFoundException -->Exception(大)
重写,子类的方法和父类必须要一致;方法体不同!
为什么要重写:
- 1、父类的功能,子类不一定需要,或者不一定满足!
快捷键:Alt+Insert,然后选择override
多态
多态
-
即同一方法可以根据发送对象的不同而采用多种不同的行为方式
-
一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多
-
多态存在的条件
- 有继承关系
- 子类重写父类的方法
- 父类引用指向子类对象
-
注意:多态是方法的多态,属性没有多态性
上代码:
父类:Person
子类:Student
启动程序:Application
多态小总结:注意事项(一定要把注意事项搞明白我们才能避免错误的发生)
- 1、多态是方法的多态,属性没有多态
- 2、必须是有父子关系 (如果没有关系转换的话会报一个异常:ClassCastException!)
- 3、多态存在条件:(1)需要有继承关系 (2)方法需要重写 (3)父类型引用指向子类对象
- 有些方法不能重写:
- 1、static 方法是属于类的,它不属于实例
- 2、final 常量
- 3、private方法是私有的也不能重写
- 有些方法不能重写:
instanceof和 类型转换(引用类型)
instanceof
instanceof:判断一个对象是什么类型(有父子关系就ok,没有就不行)
演示:
父类:Person
子类:Student
子类:Teacher
启动程序:Application
得出结论:System.out.println(x instanceof y);
- 能不能编译通过主要看x的引用类型跟y是否存在父子关系(如果存在编译通过,如果不存在编译不通过)
- 而结果主要看x指向的实际类型是不是y的子类型(就是说x指向的类型跟y有关系就为true)
类型转换
父类:Person
子类:Student
启动程序:Application
多态总结:
- 1、父类引用指向子类的对象
- 2、把子类转换为父类,向上转向
- 3、把父类转换为子类,向下转型;强制转换
- 4、方便方法的调用,减少重复的代码!使代码变简洁!
这些大家可能会很懵,都是一些理论知识,每个人的理解能力不一样,知道怎么用就行,等后面用到了,你自然就懂了,后面自己慢慢悟,别着急!别着急!别着急!
static关键字详解
static:加在属性上叫静态属性,加在方法上叫静态属性
一个类里面的静态属性或方法在内存中是和类一起加载的,能通过类调用(在本类中甚至能直接写);非静态的则需要通过new
代码块(补充)
执行结果:
静态代码块
匿名代码块
构造方法
匿名代码块
构造方法
通过执行结果我们发现:静态代码块最优先,其次才是匿名代码块,最后才执行构造方法,且静态代码块只执行一次
匿名代码块我们一般用来赋一些初始值
静态导入包(一般人很少这么玩,知道有这个东西就行)
主要说一下:通过final修饰的类就不能被继承了(意思就是断子绝孙了哈哈哈)
抽象类和接口
抽象类
-
abstract修饰符可以用来修饰方法也可以用来修饰类,如果修饰方法,那么该方法就是抽象方法;如果修饰类,那么该类就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定要声明为抽象类
-
抽象类,不能使用new关键字来创建对象,它是用来让子类继承的。
-
抽象方法,只有方法的声明,没有方法的实现,它是用来让子类实现的。
-
子类继承抽象类,那么就必须要实现抽象类没有实现的抽象方法,否则该子类也要声明为抽象类
父类:Action
子类:A
抽象类并不是我们的重点,了解一下就好了;下面的接口跟抽象类非常像用的人也比较多(接口可多继承)
接口
-
普通类:只有具体实现
-
抽象类:具体实现和规范(抽象方法)都有! 业余约束!
-
接口:只有规范!自己无法写方法~专业的约束! 能干约束和实现分离:面向接口编程
-
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是...则必须能...”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你是好人,则必须干掉坏人;如果你是坏人,则必须欺负好人。
-
接口本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
-
OO的精髓,是对对象的抽象,最能体现这一点的就是接口。为什么我们讨论设计 模式都只针对具备了抽象能力的语言(比如c++、java、c#等),就是因为设计模式所研究的,实际上就是如何合理的去抽象。
声明类的关键字是class,声明接口的关键字是interface
接口:UserService
接口:TimeService
接口的实现:UserServiceImpl
接口的点作用:
- 1、约束
- 2、定义一些方法,让不同的人实现(比如你有10个员工,但是他们都会去完成一份共同的工作,10个人实现的是一个接口,但是有10种不同是实现方式)
- 3、方法都是:public abstract 属性都是:public static final,一般没人会去玩属性
- 4、接口不能被实例化~接口中没有构造方法
- 5、可以通过implements实现多个接口
- 6、实现接口必须重写接口里面的方法
抽象的思想很难锻炼 :Java谁都会对吧 那么为什么有些人能做到架构师有些人不能 (架构师就需要抽象思维非常非常好,你要把一个系统的结构全部抽象成接口,你能通过接口去定义一个系统的时候,那时你的架构能力就已经很强了,但是大部分人做不到)
内部类
-
内部类就是在一个类的内部在定义一个类,比如,A类中定义了一个B类,那么B类相对A类来说就称为内部类,而A类相对B类来说就是外部类。
-
1、成员内部类
测试:Application
- 2、静态内部类
- 3、局部内部类
- 4、匿名内部类
- 5、也叫内部类
大家这里先了解一下就可以,讲内部类主要目的是让大家知道有这个东西,以后分析源码看到,不要不知道这是什么东西就行
本章内容较多,建议看两遍以上,第二遍你会发现一些第一遍不理解的,慢慢理解了
本章内容较多,建议看两遍以上,第二遍你会发现一些第一遍不理解的,慢慢理解了
本章内容较多,建议看两遍以上,第二遍你会发现一些第一遍不理解的,慢慢理解了
__EOF__

本文链接:https://www.cnblogs.com/xiaodi-CISP-PTE/p/16040354.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理