面向对象的思想
1.概述
- 面向对象是基于面向过程的思想
二者区别在于处理问题的方式不同
面向过程:将解决问题的过程拆成方法,执行每个方法解决问题
面向对象:强调的是对象,然后由对象去调用功能
2.思想特点
- 更符合我们思想习惯的思想
- 复杂的事情简单化
- 将我们从执行者变为了指挥者
- 举例:
我让同学带饭
我只需要等饭(面向对象)
怎么买饭就是同学的事情(面向过程)
3.面向对象开发
- 不断地创建对象,使用对象,指挥对象做事情
4.面向对象设计
- 管理和维护对象间的关系
5.面向对象三大特征
- 封装(encapsulation)
将对象的状态信息隐藏于对象内部,不允许外部对象直接访问对象内部信息
- 继承(inherritance)
子类拥有父类所以属性和方法,但对于私有方法只是拥有,不能访问
- 多态(polymorphism)
父类引用指向父类对象,若子类重写父类方法则使用子,否则使用父
对象
1.概念
- 该类事物的具体表现形式,具体存在的个体
- 比如:麻雀
- 万物皆对象
2.创建对象格式
类名 对象名 = new 类名/构造函数名();
- 实例化(创建对象时)时会初始化类的成员,如果没有赋值会初始化为该数据类型的默认值
- 一个引用指向0个或1个实例,一个实例可以有多个引用
- 创建对象语句图解
3.内存图解
- Java内存图解
- 一个对象
- 两个对象
- 三个对象
4.匿名对象
- 概述:没有名字的对象,是一种简单化表现形式
- 格式:new 类名(…);
- 应用场景
1.调用类中方法且仅调用一次,调用多次时不合适
new 类名().类中方法名();
2.可作为实际参数传递
对象名.对象中的方法(new 类名());
- 优点:调用完毕就是垃圾,可以被垃圾回收器回收
5.对象相等与引用相等的区别
- 对象相等:内存中的内容相等
- 引用相等:内存地址相等
类
1.概述
- Java语言中最基本的单位:类
- 一组相关的属性和行为的集合,是一个抽象概念
属性:该事物的描述信息————成员变量
行为:该事物能够做什么————成员方法
- 比如:鸟类(而不是XX鸟)
2.成员变量
- 使用格式:对象名.变量名
- 注意事项
1.在自己定义的类中局部变量名称可以和成员变量名称一样,在方法中使用的时候
采用**就近原则**
- 成员变量与局部变量的区别
1.在类中位置不同
成员变量:在类方法外
局部变量:在方法定义中或在方法声明上
2.在内存中位置不同
成员变量:在堆内存
局部变量:在栈内存
3.生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
4.初始化值不同
成员变量:有默认初始值
局部变量:没有默认初始值,必须定义,赋值后才可以使用
3.封装 private
- 只能在本类中访问,外界不可以直接访问
- 概述:隐藏对象的属性和实现细节,仅对外提供公共访问方式
- 优点
1.隐藏实现细节,提供公共的访问方式
2.提高了代码的复用性
3.提高了安全性
- 实现原则
1.将不需要对外提供的内容都封装隐藏起来
2.将属性隐藏,提供公共方式对其访问
建议:属性私有化,方法公有
- 关键字 private
概述:
是一个限权修饰符
可以修饰成员(成员变量和成员方法)
被其修饰的成员只能在本类中才能访问
常见应用:
将所有的成员变量用private修饰
提供对应的getXXX/setXXX方法(获取值/赋值)
4.关键字 this
- this代表所在类的对象引用,简单记this就代表当前类的一个对象——被哪个对象调用,this就代表那个对象
- 使用场景:局部变量隐藏成员变量
- 作用
在成员方法中,this.变量名
可用于访问成员变量
若没有this关键字,就近原则
- 私有类间接访问规范
赋值:setXXX();
private String sex;
public void setSex(String sex){
this.sex = sex;
}
取值:getXXX();
private String sex;
public String getSex(){
return sex;
}
5.构造方法 constructor
- 概述
给对象的数据进行初始化===set方法一样用于赋值
**最佳实践:提供一个无参和带所有参数的构造函数 其他结合setter方法
- 格式
1.方法名与类同名
2.无返回值类型,连void都没有
3.没有具体返回值
public 类名(...){...}
---> (...)中可以有参可以无参
- 注意事项
1.若不提供构造方法,系统会默认给出无参构造函数
2.若提供了构造方法,系统将不再提供无参构造函数
3.构造方法可以重载,但不能重写
- 创建对象(new)的时候自动调用构造函数
类名 变量名 = new 类名(...)
....中无参即调用无参构造方法
....中有参即调用有参构造方法
6.成员方法
- 使用格式:对象名.方法名(…)
- 形参与返回值问题
XXX做形参
1.基本类型:形参的改变不影响实参
2.引用类型:形参的改变直接影响实参(因为实际上改变的是地址值)
类名:需要该类的对象
抽象类名:需要该类子类对象
接口名:需要该接口的实现类对象
返回值类型
1.基本类型:形参的改变不影响实参
2.引用类型
类:返回的是该类的对象
抽象类:返回的是该类的子类对象
接口:返回的是该接口的实现类对象
- 链式编程
对象.方法1(). 方法2().......方法n()
方法1调用完毕后返回一个对象
方法2调用完毕后返回一个对象
方法n调用完毕后返回可能是对象,也可以不是
7.关键字 static
- 访问格式:类名.static变量/方法名
- 特点
1.被类的所有对象共享**
2.静态变量随着类的加载而加载,随着类的消失而消失
3.优先于对象存在,生命周期伴随整个程序
4.通过类名调用(推荐),也可以通过对象名调用
- 内存图解
- 注意事项
1.在静态方法中没有this关键字**
静态是随着类的加载而加载
this是随着对象的创建而存在
静态比对象先存在
2.静态方法只可以访问静态的成员变量和静态的成员方法
因为非静态成员不存在时静态方法就已经存在,访问不存在的成员属于非法调用
3.非静态方法可以访问所有成员(包括静态与非静态) 但不可以定义静态局部变量
4.main是一个静态的,它访问
静态方法时
格式:方法名(....)
非静态方法时
格式:类名 对象名 = new 类名(....)
对象名.方法名(....)
5.程序运行的时候static修饰的就被加载,而不被修饰的要创建对象(new)时才会加载(即分配内存空间)
6.非静态成员的生存期决定于该类的生存期,而静态成员生存期则与程序生命期相同
- 静态变量与成员变量的区别
1.所属不同
静态变量属于类,所以也称为类变量
成员变量属于对象,所以也称为对象变量
2.内存中位置不同
静态变量储存于方法区的静态区
成员变量储存于堆内存
3.生命周期不同
静态变量随着类的加载而加载,随着类的消失而消失
成员变量随着对象的创建而存在,随着对象的消失而消失
4.调用不同
静态变量可以通过类名调用,也可以通过对象调用
成员变量只能通过对象名调用
5.访问限制不同
静访静,非静访所以
8.main方法的格式讲解
public static void main(String[]args)
- public:公共的
访问权限最大
由于main方法是被jvm调用,所以权限要够大
- static:静态的
不需要创建对象,通过类名就可以
方便jvm的调用
- void
方法的返回值给调用者,而main方法是被jvm调用,所以返回内容给jvm没有意义
- main:常见的方法入口
- String[] args:字符串数组
早期为了接收键盘录入数据
控制台输入 java 类名 a1 a2..(args内容)
9.代码块
- 概念:代码块用{}括起来
- 局部代码块
位置:局部位置(方法中)
作用:限定变量的生命周期,及时释放提高内存利用率
- 构造代码块
位置:类中的成员位置,用{}括起来的代码
每次调用构造方法执行前都会先执行构造代码块**
作用:将多个构造方法中的共同代码放在一起,对对象进行初始化
- 静态代码块
位置:类中的成员位置,用{}括起来的代码,但是用static修饰
只执行一次**
作用:对类进行初始化
- 执行顺序
先执行静态代码块(只执行一次)
再执行构造代码块(每次调用构造方法都执行)
最后执行构造方法
与语句放置的顺序无关
10.继承 extends
- 使用场景
1.多类中存在相同属性和行为时,可将这些属性放在一个单独类中,只需继承此类即可使用(代码重用)
2.继承实际体现的是一种“is a”的关系
3.采用假设法:如果有两个类A,B,只要符合A是B的一种或者B是A的一种即可以考虑使用继承
- 格式
class 子类名 extends 父类名{}
父类:基类或者超类
子类:派生类
- 好处
1.提高了代码的复用性,同一功能放于同一类中
2.提高了代码的维护性,出问题修改一处即可
3.让类与类产生了关系,是多态的前提
- 坏处
1.让类与类产生了关系,使类的耦合性增强,增加后期维护的难度
开发原则:低耦合,高内聚
耦合:类与类的关系
内聚:自己完成某件事的能力
2.打破封装性
- 特点
1.只支持单继承(C++支持多继承)
class 子类名 extends 父类名1,父类名2{}====不支持
一个儿子一个爹,但爹可以有多个儿子
2.支持多层继承
class A{}
class B extends A{}
class C extends B{}
继承只是单方向的 子可访问父 父不可访问子
- 注意事项
1.子类只能继承父类所有的非私有的属性和方法
2.子类不能继承访问父类的构造方法,但可以通过super关键字访问
3.不要为了两个类中的部分功能而去使用继承
4,当创建子类对象时,先创建父类对象,再完成创建子类对象,若父类对象创建失败,则无法创建子类对象
5.当创建子类对象时,先完成父类中成员初始化,再调用父类构造函数,再完成子类初始化,再调用子类构造函数
6.每个子类构造函数都默认先调用父类 无参 构造函数
- 继承中成员变量的关系
1.子类中的成员变量名与父类中的成员变量名不一样
2.子类中的成员变量名与父类中的成员变量名一样,**就近原则**
子类方法的局部范围找,有就使用
子类成员范围找,有就使用
父类成员范围找,有就使用
都没有就报错
3.子类中的局部变量,成员变量及父类中的成员变量的变量名相同
输出本类局部变量(局部方法):变量名(方法名)
输出本类成员变量(本类成员方法):this.变量名(本类成员方法)
输出父类成员变量(父类成员方法):super.变量名(父类成员方法)
- 继承中构造方法的关系
1.子类的每一个构造方法的第一条语句默认都是super(),无super关键字,子类所有构造方法也默认先访问父类中的无参构造方法,访问完后再执行自己的构造方法 ,为子类访问父类数据初始化
注意:用了super就不要再使用this
2.若父类中没有无参构造方法,子类中的构造方法会报错,怎么解决?
方法1:在父类中加一个无参构造方法
方法2:通过super关键字访问父类的有参构造方法
方法3:子类通过this去调用本类的构造方法
3.this()和super()必须出现在第一条语句上,且不能同时出现,否则就会出现父类数据多次初始化
注意:子类中一定要有一个去访问了父类的构造方法,否则父类数据就没有初始化
4.类的初始化过程
成员变量初始化(默认值初始化->显示值初始化)
->构造方法初始化
5.父类初始化->子类初始化
6.静态代码块父->静态代码块子->构造代码块父->构造方法父->构造代码块子->构造方法子
11.关键字 super
- 作用
指向当前对象的父类,可以操作父类的成员,调用父类构造函数
- 格式
super(参数列表)
只能放在子类构造函数的第一行使用
super.成员变量
- 用了super就不要再使用this
12.重载 overload
- 相同点
1.方法实现功能相同
2.方法名相同
- 不同点
1.参数类型不同
2.参数数量不同
3.参数类型顺序不同
注意:与 参数名 顺序无关
- 特点
1.与方法返回值无关
2.作用在同一作用域 = 发生在同一个类内部
3.当遇到重载函数的时候,编译器如何根据参数选择?(取决于编译器)
答:完全匹配+类型提升
4.构造方法可以重载,静态方法也可以重载
13.重写 override
- 概述:子类和父类中出现了一模一样的方法声明
- 应用:当子类需要父类功能,而功能主体子类有自己特有的内容时
- 注意事项
1.父类中的私有方法不能被重写(父类私有方法子类根本就无法继承)
2.父类静态方法子类也必须通过静态方法进行重写
3.子类重写父类方法时最好声明一模一样
- 特点
1.两同:方法名、形参列表相同
2.两小:返回值类型、抛出异常更小
3.一大:访问修饰符
14.关键字 final
- 概述
修饰类,方法和变量
- 特点
1.修饰类:该类不能被继承
2.修饰方法:该方法不能被重写
3.修饰变量:该变量不能被重新赋值==常量
- 注意
final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销
final关键字提高了性能,JVM和Java应用都会缓存final变量
使用final关键字,JVM会对方法、变量及类进行优化
- 思考题
15.多态
- 概述:同一对象在不同时刻表现出的不同状态,同一引用名创建不同对象
- 格式
父类名 对象名 = new 子类名()
- 前提
1.有继承extends或实现接口关系
2.有方法重写
3.有父类或父接口引用指向子类对象 fu f = new zi();
- 成员访问特点
1.成员变量:
编译看左边(f),运行看左边(f)
2.构造方法:
构造子类对象时,先访问父类的构造方法,对父类的数据进行初始化
3.成员方法:
编译看左边(f),运行看右边(z)(成员方法存在方法重写所以看右边)
4.静态方法:
编译看左边(f),运行看左边(f)(静态与类相关算不上重写所以还是访问左边)
- 分类
具体类多态
class Fu{}
class Zi extends Fu{}
Fu f = new Zi();
抽向类多态(常用)
abstract class Fu{}
class Zi extends Fu{}
Fu f = new Zi();
接口多态(最常用)
interface class Fu{}
class Zi implements Fu{}
Fu f = new Zi();
- 种类
静态多态:重载
1.在编译时决定调用哪个方法——编译时报错
2.重载是否发生与继承没有必然联系
动态多态:重写
1.在运行时决定调用哪个方法——运行时抛出异常
动态多态实现前提:继承,重写,必须由基类引用指向派生类对象,且通过基类的引用调用被覆盖的方法
- 优点
1.提高了代码的维护性(继承保证)
2.提高了代码的扩展性
一种函数多种形态,调用同一个函数得到不同结果
- 弊端
不能使用子类中特有的方法,只能使用重写方法
解决方法
1.创建子类对象调用方法zi z = new zi()
2.(推荐)向下转型**:将父类的引用强制转换为子类的引用
- 多态内存图解
16.转型
- 向上转型
父类名 dx=new 子类名()
父类引用 = 子类对象
只能调用子类重写方法,不能调用子类特有的
且调用自己的成员变量
若方法没有被重写,则调用父类自己的成员方法
- 向下转型(强转)
Parent p = new Son()
Son s = (Son)p;
Son p = (Son) new Parent();===不行
- 强转内存图解
17.抽象 abstract
- 抽象方法
格式:权限修饰符 abstract 返回值 方法名(形参列表)
使用:某方法没有必要实现,但又不可少
- 抽象类
1.概述:不是具体的功能称为抽象功能,而一个类中有抽象的功能该类必须是抽象类
2.格式:abstract class 类名{}
3.注意
抽象类中不一定有抽象方法,但有抽象方法的类必须定义为抽象类
抽象类有构造方法,但只能用于继承,不能实例化(new),构造方法用于子类访问父类数据的初始化
抽象类派生出的子类必须提供抽象类所有的抽象方法的具体实现,若没有全部实现抽象方法,则该子类也必须定义为抽象类
4.抽象类的成员特点
成员变量:既可以是变量也可以是常量
构造方法:用于子类访问父类数据的初始化
成员方法:可以是抽象的也可以是非抽象的
5.抽象类中不能有的关键字
private 冲突——导致不能重写
final 冲突——导致不能重写
static 无意义
6.抽象类中没有抽象方法也可以定义为抽象类,有什么用?
为了不让创建对象
- abstract只能修饰方法和类
18.接口 interface-implement
- 概述:接口不是实际意义上的类,仅仅表示功能的扩展
- 接口类interface
格式:
权限修饰符 interface 接口名{
定义方法中可以省略abstract关键字
}
类中所有方法都是抽象方法,没有方法体
接口名建议I开头
特点
1.接口是一种抽象的类型,不能被实例化,按照多态的方式实例化
2.不能有main方法
接口子类
可以是抽象类,但意义不大
可以是具体类,要重写接口中所有的抽象方法
接口成员
1.成员变量
只能是常量,并且是静态的
默认修饰符:public static final
2.构造方法:接口没有构造方法
3.成员方法
只能是抽象的
默认修饰符:public abstract
- 接口实现类implement
格式:class 实现类 implements 接口{}
- 特点
1.一个实现类可以实现多个接口
class 实现类 implements 接口1,接口2{}
2.继承父类的同时可以实现接口
class 子类 extends 父类 implements 接口{}
19.类-接口关系与区别
- 类与类的关系
依赖(使用) use a
public void show( Parent p){}
组合(包含) has a
一个类中包含另一个类
继承关系(父子) is a
只能单继承,可以多层继承
- 类与接口的关系
实现关系
可以单继承,可以多继承,还可以在继承一个类的同时实现多个接口
- 接口与接口的关系
继承关系
可以单继承,可以多继承
- 抽象类与接口的区别
1.成员区别
抽象类
成员变量:可以变量也可以常量
构造方法:有
成员方法:可以抽象也可以非抽象
接口
成员变量:只可以是常量
构造方法:无
成员方法:只可以是抽象
2.关系区别
类与类:继承,单继承
类与接口:实现,单实现,多实现
接口与接口:继承,单继承,多继承
3.设计理念区别
抽象类:被继承体现的是is a的关系,抽象类中定义的是共性功能
接口:被实现体现的是like a的关系,接口中定义的是扩展功能
20.类中类对象的赋值
- 方法一:在类1中成员变量的位置创建类2对象,在测试类3中创建类1对象后,测试类3中
赋值语句:类1对象.类2对象.类2成员变量 = XXXX;
- 方法二:在测试类3中创建类2对象并赋值,再创建类1对象后,测试类3中
赋值语句:类1对象.类2对象 = 类3中类2对象
内部类
包
1.作用
- 对类进行分类管理
按功能分
按模块分
- 把相同的类名放在不同的包中
2.格式
- package 包名;(多级包用.分开)
3.包名
- com.公司名.项目名
4.注意事项
- package语句必须是程序的第一条可执行代码
- package语句在一个Java文件中只能有一个
- 如果没有package默认表示无包名
5.带包的编译运行
- 手动式
编写一个带包的Java文件
通过Javac命令编译该Java文件
手动创建包名
把第二步的class文件放到第三步的最底层包
回到和根目录在同一目录的地方
然后运行
- 自动式
编写一个带包的Java文件
javac编译时带上-d .即可
javac -d . xxx.java
6.导包
- 使用背景:多次使用一个带包的类,非常麻烦,所以导包import
- 格式: import 包名…类名
- 注意:此方式导入的是类的名称,用谁就导谁
7.不同包下同名类的访问
- case01下的Person类
import com.yc.oop2.case01.Person;
Person p = new Person();
- case02下的Person类
包的全路径.类名
com.yc.oop2.case02.Person p1 = new com.yc.oop2.case02.Person();
8.package import class顺序关系
- package>import>class
package:只能有一个
import:可以有多个
class:可以有多个,建议是一个
修饰符总结
1.权限修饰符
- private——只有本类可以用
- 默认
- protected
- public
- 访问情况
> 在本类中四种都可以访问
> 同一包下(子类和无关类)除私有的都可以访问
> 不同包下(子类)protected与public可以访问
> 不同包下(无关类)public可以访问
- 这四种修饰符在任意时刻只能出现一种
2.状态修饰符
- static 修饰内部类,方法,字段
- final 修饰类、字段、方法
3.抽象修饰符
- abstract 修饰类和方法
4.修饰符的使用
- 类
默认修饰符:class 类名{}
public修饰符:public 类名{}===(用的最多)
final修饰符:public final class 类名{}
abstract修饰符
- 成员变量
private修饰符:private int x =10; (用的最多)
默认修饰符:int x = 10;
protected修饰符:protected int x = 10;
public修饰符:public int x = 10;
static修饰符:public static int x = 10;
final修饰符:public final int x = 10;
static+final修饰符:public static final int x = 10;
- 构造方法
private修饰符:private 类名(...){...}
默认修饰符:类名(...){...}
protected修饰符:protected 类名(...){...}
public修饰符:public 类名(...){...} (用的最多)
- 成员方法
所有的修饰符都可以(用最多的是public)
基本类的标准代码写法
1.类
- 成员变量
- 成员方法
getXXX()
setXXX()
- 构造方法
带所有参
无参
2.给成员变量赋值的方法
- 无参构造方法+setXXX() ==== 开发中常用(灵活性高)
- 有参构造方法
3.输出成员变量值的方式
- 通过getXXX()分别获取然后拼接
- 通过调用该类中函数搞定
基本概念
- 复合数据类型是通过类或者接口
- 虚函数即没有final关键字的函数
- 实例方法即非静态方法
意思就是他属于类的某个实例,通过这个实例调用它,对类的其他实例不产生影响.
- 类方法即该类的静态方法
方法属于这个类本身,不属于他的任何实例
意思就是说,这个方法可以不通过实例调用,并且所有的实例都共享这一个方法,对方法的调用各个实例相互可见
- 静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员函数不能访问非静态的成员
- 3种构造函数分别是a(基类的构造函数),b(成员对象的构造函数),c(派生类的构造函数 )这3种构造函数的调用顺序为: abc
补充
1.eclipse的简单介绍
2.软件设计原则
- 高内聚,低耦合
尽可能在一个类中实现,减少类与类之间的联系
- 对外开放,对内关闭
在当前系统基础上可以添加类,已存在的代码不去修改
3.关键字instance of
obj instanceof Person
——判断obj对象是不是Person类