面向对象
- 1.类和对象
- 2.编写面向对象的代码(重点)
- 第一步:编写类
- 第二步:==编写属性==也叫做==编写成员变量==或者叫做==字段==
- 第三步:编写方法
- 第一种方式:光标放在类中,按**Alt + Insert**键,选择第一项**Constructor**构造器、构造方法、构造函数,按回车键,按两次**Tab**键,再按回车,则==生成无参构造方法==
- 第二种方式:光标放在类中,按**Alt + Insert**键,选择第一项**Constructor**回车,鼠标左键点击第一个要赋值的属性,然后再按Ctrl +鼠标左键点击其他要赋值的属性,最后按回车键,则生成带参构造方法,完成对部分属性赋值
- 第三种方式:光标放在类中,按**Alt + Insert**键,选择第一项**Constructor**回车,按**Ctrl + A**全选,再按回车键,则生成带参构造方法,完成对所有属性赋值
- this关键字访问本类中的实例方法
- 3.封装
- 4.继承(重点):
- 5.Static 关键字
- 6 final 关键字修饰类
- 7. 多态
- 8. 提取方法
- 9. 抽象类和抽象方法(重点)
- 10. 接口(重点)
- 11. 内部类
- 12. Object类(重点)
- 13. 类与类之间的语言
- 14. 递归(了解)
1.类和对象
2.1概念:
-
面向对象:虚拟世界模拟现实生活,必须要保证模拟一致
-
面向过程:按照顺序(步骤)逐步完成
-
类:
对同一类事物的抽象的描述,也就是:不仅具体的
例:电脑类、水杯类、人类、动物类、鱼类…… -
对象:
万物皆对象,(具体的实例)
例:我的电脑、某某的水杯 -
类与对象之间的关系
抽象与具体的关系 -
描述对象的特征,称为属性
例:颜色、尺寸、品牌、价格…… -
对象实现的功能,或者对象所做的事情,称为方法
例:打电话、拍照…… -
张三对象:
属性:姓名、性别、身高、体重、年龄、电话号码、家庭住址……
方法:学习、说话、吃饭、睡觉……
-
李四对象:
属性:名字、年龄、性别、身高、体重、身份证号………
方法:玩游戏、跑步、打篮球、学习…….
-
将多个对象找到相同的属性和方法组合在一起形成一个类
例
-
学生类
属性:姓名、年龄、性别、身高、体重
方法:学习
-
2.编写面向对象的代码(重点)
第一步:编写类
-
编写类的语法格式:
[修饰符] class 类名{
}
注意事项:
- 在面向对象中,类名建议:编写单词,每个首字母大写
第二步:编写属性也叫做编写成员变量或者叫做字段
-
注意事项:
-
属性编写在类中;
-
编写属性语法格式:
[修饰符] 数据类型 属性名 [= 值 ]; -
属性名也就是标识符,建议:编写单词,并且采用驼峰命名
-
当创建对象后,如果属性没有赋值则是有默认值的,数据类型不同默认值不同,具体如下:
-
整数类型默认值为0
-
浮点类型默认值为0.0
-
字符类型默认值为\u0000
-
布尔类型默认值为false
-
所有引用数据类型默认值为null
-
-
第三步:编写方法
-
方法的语法格式:
[修饰符] 返回值类型 方法名称 ([参数列表]){
方法体
}
-
在面向对象中,方法的修饰符==暂时==编写为public
-
编写测试Test类
- 其实就是包含main方法的类
- test 测试
- 创建对象
- 语法格式:类名 引用名 = new 类名();
- 注意:一个类可以创建任意多个对象
-
访问对象中的属性和方法
5.1 访问对象属性中的属性
- 获取属性的值
引用名.属性名 - 对属性赋值
引用名.属性名 = 值;
5.2访问对象中的方法
- 引用名.方法名称([参数列表]);
- 注意:在面向对象中,方法没有编写static,因此不能使用类名. 否则就出现编译错误
- 获取属性的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UueqSzJS-1669733051474)(C:\Users\86136\AppData\Roaming\Typora\typora-user-images\image-20210608192642455.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YqdUQwzC-1669733051475)(C:\Users\86136\AppData\Roaming\Typora\typora-user-images\image-20210608192647588.png)]
6.局部变量与成员变量区别(重点、难点)
6.1 声明位置不同
-
局部变量:在方法中声明的变量
-
成员变量:在方法外面声明的变量或者在类中声明的变量
6.2 作用范围不同
-
局部变量:在当前声明距离最近的大括号内使用,作用范围相对更小
-
成员变量:在本类(当前类)中可以直接使用,称为全局变量,作用范围相对更大
6.3 初始值不同
-
成员变量:0当创建对象后,如果没有对象成员变量赋值,则成员变量是有默认值的,数据类型不同默认值不同
-
局部变量:没有默认值,也就是说:局部变量必须要先声明,然后再赋值,最后才可以使用
6.4 在同一个类中,局部变量的名字与成员变量的名字相同,不报错,但是局部变量优先,也就是:就近的优先,如果非要使用成员变量,则必须使用this.
- 在Java中,this代表当前这个对象,也就是:当前谁调用这个方法则这个对象就是谁
7.构造方法以及构造方法的重载:
构造方法:
1.构造方法作用(重点)
完成对属性赋值
2.构造方法是一个特殊的方法,主要有以下两点:
构造方法的名字必须与类名一致
构造方法必须没有返回值类型,也就是:都不需要编写void
3.构造方法的语法格式
public 类名([参数列表]){
}
4.构造方法快捷键(重点)
第一种方式:光标放在类中,按Alt + Insert键,选择第一项Constructor构造器、构造方法、构造函数,按回车键,按两次Tab键,再按回车,则生成无参构造方法
注意:大多数情况下,无参构造方法体中不编写任何内容**,**也就是:执行无参构造方法时,属性都是默认值
第二种方式:光标放在类中,按Alt + Insert键,选择第一项Constructor回车,鼠标左键点击第一个要赋值的属性,然后再按Ctrl +鼠标左键点击其他要赋值的属性,最后按回车键,则生成带参构造方法,完成对部分属性赋值
第三种方式:光标放在类中,按Alt + Insert键,选择第一项Constructor回车,按Ctrl + A全选,再按回车键,则生成带参构造方法,完成对所有属性赋值
5.构造方法如何执行?(重点)
当创建对象时,会自动找相匹配的构造方法执行
1.当编写new之后,敲一个空格,然后编写部分类名的字母,则就会出现提示框,可以按方向键上键或者下键进行选择要执行的构造方法,
3.注意事项:
当没有在IDEA中设置,如果编写new之后,敲一个空格,然后再编写部分类名时,则没有选择要执行哪个构造方法,则查看是否在类中编写多个构造方法,如果编写构造方法,则需要进行如下设置
File—>Settings—>Editor—>General—>Code Completion—>右侧将参数基本设置中的第一项和担心勾上—>
6.构造方法注意事项:
6.1当在一个类中没有编写构造方法,则系统会提供一个默认的无参的构造方法,也称为隐式构造方法
也就是说:当一个类中没有编写构造方法,则有一个无参构造方法
6.2当在一个类中编写构造方法,则系统不会提供无参的构造方法,也称为显式构造方法
也就是说:当一个类中编写几个构造方法,则就共计有几个构造方法
6.3建议:当编写构造方法时,先编写无参构造方法,然后再编写需要的带参构造方法,否则在后面使用无参构造方法时,没有无参构造方法,则就会出现编译错误
7.构造方法重载
7.1什么是构造方法重载?
在同一个类中,构造方法的名字必须相同,参数列表必须不同(个数不同、类型不同、顺序不同),至少编写2个构造方法
7.2当构造方法构成重载后,如何确定执行的是哪个构造方法?
在创建对象时,会根据实参的值自动找相匹配的构造方法执行,否则出现编译错误
7.3构造方法重载好处
在使用时,相对更灵活
-
变量按数据类型分为
-
基本数据类型:在**内存中存放的是真正的值**
-
引用数据类型:在内存中存放的是地址(引用)
类(class)- 系统提供的类,比如:string、……
- 用户自定义的类,比如:Car、Student、Computer……
- 对引用数据类型赋值方式有两种
- 第一种:将对象的内存地址赋给左侧的引用名称
c = new Car(); - 第二种:将null值赋给左侧的引用名称
c = null;
- 第一种:将对象的内存地址赋给左侧的引用名称
-
-
空指针异常
- 属于运行错误 java.lang.NullPointerException
-
出现空指针异常原因:
- 当前引用名中存放的是null,也就是没有存放某个对象的地址,因此就没有指向某个对象,则就不能访问对象中的属性或方法,如果非要访问则就出现空指针异常
3.解决办法:
- 在访问对象中的属性或方法之前,必须保证引用名中存放的是地址(引用)
-
参数传递
- 基本数据类型作为参数传递
基本数据类型在内存中存放的是真正的值,- 因此:实参传递给形参的是真正的值,也就是拷贝一份,当另一个方法局部变量的值更改,对原来方法中局部变量的值没有任何影响
- 基本数据类型作为参数传递
-
引用数据类型作为参数传递
引用数据类型在内存中存放的是地址(引用)
- 实参传递给形参的是地址(引用),也就是:实参与形参存同一个地址,指向同一个对象,当另一个引用名中的属性值发生改变,对原来引用名中的属性值有影响;
3. 对象中的属性可以是用户自定义数据类型
-
this关键字
- 在java中,this代表当前这个对象,也就是:当前谁调用这个方法,则这个对象就是谁
- 在java中,this关键字可以访问本类(当前类)中的实例变量,实例方法以及本类中的其他构造方法
-
this关键字访问本类中的实例变量(重点)
- this关键字可以访问本类中的实际变量:
- 当属性(成员变量或者字段)前面没有编写static关键字称为实例(对象)变量
- 实例变量什么时候存在?
当创建对象时,会在堆内存的对象开辟空间存储 - 当没有局部变量与实例变量同名,则可以在本类中直接使用实际变量,默认在实际变量前面添加this.
- 在同一个类中,局部变量与实例变量可以同名,不报错,但是就最近的优先也就是局部变量优先,
如果非要实例变量,则必须编写为this.
this关键字访问本类中的实例方法
* 2.1当方法没有使用static关键字修饰,称为实例方法,也就是对象的方法
* 2.2当访问本类中的实例方法时,默认前面编写this.
* 比如:print(); 其实等价于this.print();
3. this关键字还可以访问本类中的其他构造方法
3.this关键字还可以本类中的其他构造方法
3.1访问本类中的构造方法,使用this关键字
3.2如果this后面小括号中没有内容,则执行本类无参构造方法,否则执行本类相匹配的带参构造方法
3.3注意事项:
当使用this关键字访问本类构造方法时,只能编写在构造方法中,并且是第一条语句
this关键字访问构造方法时,只能访问本类中的其他构造方法,也就是:构造方法不能自己调用,死循环,没有意义
3.封装
-
1.在java,面向对象有三大特征:封装、继承、多态
-
–有时也会问面向对象四大特征:封装、继承、多态、抽象,其实抽象是面向对象程序设计的方法–
-
2.什么是封装?
-
在现实生活中,封装也就是:包装或者包裹,比如:快递、外卖…
-
在java中,封装也就是:隐藏类的内部信息,不允许外部程序直接访问,而是通过方法完成
-
3.封装的操作步骤:(重点)
-
第一步:将==实例变量前面编写private,==也就是:该实例变量只能在本类(当前类)中使用
-
第二步:编写对应实例变量的方法(取值方法和赋值方法)
- 第1种情况:光标放在类中,按Alt + Insert键,选择第二项Getter,按回车键,则生成取值方法
其中Getter表示取值方法
大多数情况下,一个实例变量对应一个取值方法get
- 第2种情况:光标放在类中,按Alt + Insert键,选择第三项Setter,按回车键,生成赋值方法
其中Setter表示赋值方法
大多数情况下,一个实例变量对应一个赋值方法set
- 第3种情况:光标放在类中,按Alt + Insert键,选择第四项Getter and Setter,按回车键,则生成取值和赋值方法
大多数情况下,一个实例变量对应一个取值方法和一个赋值方法
-
第三步:根据情况,在赋值方法set中编写判断语句
-
比如:年龄在1—150岁范围内为合法,否则实例变量年龄的值18
-
性别只能是男或女为合法,否则实例变量性别的值为女
4.封装好处:值相对更安全(也就是:值更合法或者值有效、有意义)
- 优化封装:
-
-
当set方法设置为Builder时,则该方法生成带参带返回值类型的
-
当set方法返回当前对象时,在使用时就可以进行连缀操作
返回的是当前对象可以写为:
引用名.实例变量().实例变量().实例变量();
-
4.继承(重点):
-
发现并列子类中,有相同的属性和相同的方法,则就可以使用继承完成;
第一步:将多个类中相同的(公共的)属性和方法存放在单独的一个类中,称为父类
第二步:编写子类继承父类
第三步:在子类中编写独有(特有的)属性和方法
-
继承的好处
- 减少代码的冗余性(重复性),提高代码的复用性
-
编写继承代码(重点)
-
第一步:编写父类
-
语法格式:
[修饰符] class 父类类名{ 公共的属性和方法
}
-
-
第二步:编写子类
-
语法格式:
[修饰符] class 子类类名 extends 父类类名{ 独有的属性和方法
}
-
-
注意事项:
- 在Java中,当一个类没有使用 extends 指定继承哪个父类时,则系统默认继承object类
当继承object类时,extends object 可有可无 - 在Java中,object是所有类的父类
- 在Java中,当一个类没有使用 extends 指定继承哪个父类时,则系统默认继承object类
-
-
重写override(重点、难点)
-
什么时候进行方法的重写?
当分类中的方法不能满足子类的需求,则需要在子类中重写父类中的方法
因此重写也叫覆盖 -
重写规则
Ø 在子类中重写父类的方法Ø 不能缩小访问权限
Ø 返回值类型必须一致 或者 父类方法返回值类型的子类类型
Ø 方法名称必须一致
Ø 参数列表必须一致
-
重写快捷键(重点)
光标放在子类中,按 ctrl + o 选择父类中要重写的方法,按回车键
-
重写注意事项
当子类中重写父类的方法后,再调用方法,则调用子类重写以后的方法,也就是说:父类中的方法使用不到,但是必须不能删除
-
-
继承注意事项
-
父类也叫超类,基类superclass ,子类也叫做派生类 subclass
-
子类继承父类时,不能继承父类的构造方法
-
继承满足条件:
例:猫是动物、狗是动物 -
继承有两大特性:
-
单根性:
再Java中一个类只能继承一个直接的父类,类是单继承 -
类具有传递性
-
-
class A{
有2个属性和2个方法
}
class B extends A{
独有属性5个,独有方法2个
}
class C extends B{
}
-
this关键字与super关键字的区别
-
1.this关键字代表
Ø 代表当前这个对象,也就是说:当前谁调用这个方法,则这个对象就是谁
Ø 在当前类中使用,可以访问当前类中的内容,也可以访问父类中的
2. this关键字可以访问
Ø 可以访问本类(当前类)中的实例变量、实例方法,以及本类中的其他构造方法
Ø 还可以访问父类中的实例变量和父类中的实例方法
3. this关键字访问实例变量、实例方法时,查找顺序在
Ø 先在当前类中找,如果没有找到则再去父类中找该实例变量或实例方法
-
1. super关键字代表
super代表父类也就是超类
只能在子类中使用,访问父类中的内容
2. super关键字可以访问
Ø 可以访问父类中的实例变量和父类中的实例方法
Ø 还可以访问父类中的构造方法
当子类构造方法中没有使用super关键字指定调用父类哪个构造方法,则系统默认调用父类无参构造方法
-
super关键字访问父类中的实际变量或实例变量,查找顺序
- 直接去父类中找该实际变量或实例方法
- 因此使用super. 访问父类中的实例变量或实例方法,查找速度相对更快或者执行效率更高,因此建议使用super. 访问父类中实际变量或实例方法
-
super关键字注意事项
- 不能使用super. 访问子类独有的实际变量或实例变量
-
-
当创建子类对象时,父类做了什么
先执行父类构造方法,然后再执行子类相匹配的构造方法
5.Static 关键字
表示静态的
可以修饰属性、方法、代码块、内部类以及实现静态导入
1.static关键字修饰属性
1.1在类中声明的变量,称为成员变量,也叫做属性或者叫做字段f
如果属性前面没有编写static关键字称为实例变量,也叫做对象的变量
如果属性前面编写static关键字称为静态变量,也叫做类的变量
1.2静态变量特点:
1.2.1当类加载到内存时,就给静态变量分配空间,一直到程序结束
1.2.2静态变量:在JDK8.0之前在方法区中存储
在JDk8.0之后在堆中存储
1.2.3静态变量与类同生死,也就是类在静态变量就存在,因此静态变量也叫做类的变量
1.2.4静态变量访问方式:
使用类名.静态变量名
也可以使用引用名.静态变量名
当引用名中存放的是null,依然可以访问静态变量,不会出现空指针异常,因为:静态变量不属于某一个对象,一直到程序结束
1.2.5静态变量不属于某一个对象,是当前类所有对象都可以共享
1.2.6类优先于对象,也就是说:类的生命周期比较长
1.3什么时候将属性编写为static修饰?
当多个对象中的某个属性的值都一样时,建议:编写为静态变量,原因:节省空间,并且所有对象都可以共享
3.static关键字修饰代码块
* 3.1使用static关键字修饰代码块,称为静态代码块
* 3.2静态代码块语法格式
* static{
*
* }
* 3.3静态代码块作用:完成对静态变量赋值
* 3.4静态代码块怎么执行?
* 当类加载到内存时,执行静态代码块,并且只执行一次
4.static关键字修饰内部类
* 4.1什么是内部类
* 在一个类中,再编写一个类,里面的这个类,称为内部类,也叫做内置类或者嵌套类
* 4.2一般什么时候编写内部类?
* 内部类是对外部类提供服务的,如果内部类还想对其他外部类提供服务,则不建议编写为内部类
* 4.3当在内部类前面编写static关键字,称为静态 内部类
- static 关键字可以实现静态导入
2.5访问权限
-
类的访问权限
公共类和非公共类
- 当一个类前面你编写 public 修饰符,当类称为公共类,也就是:该类可以在任意包中都可以使用
- 当一个类前面没有编写public 修饰符,该类称为非公共类,也就是:该类只能在当前类中使用
-
成员的访问权限
访问权限 在当前类中 在当前包中 不同包的子类 任意包任意类 private私有的 可以使用 不可以使用 不可以使用 不可以使用 默认的 可以使用 可以使用 不可以使用 不可以使用 protected受保护 可以使用 可以使用 可以使用 不可以使用 public公共的 可以使用 可以使用 可以使用 可以使用 Ø 总结:
1.当属性没有要求时,建议:使用默认访问权限
2.当要求使用封装完成,建议:实例变量编写为private访问权限
3.当成员要求在当前类以及子类中使用, 建议:成员使用protected访问权限
4.大多数情况下,方法使用public访问权限
-
重写 override也叫做覆盖
-
在子类中重写父类的方法
-
不能缩小父类的访问权限
-
返回值类型一致 或者编写为父类方法返回值类型的子类类型
-
方法名称必须一致
-
参数列表必须一致
-
6 final 关键字修饰类
- final 表示最终的
- 可以修饰类、属性、方法
- final 关键字修饰类
-
当使用final关键字修饰类,表示该类就是最终的类,也就是:不能被继承
-
使用final修饰的类,比如:String System Scanner ……
-
final 关键字修饰属性(重点):
final关键字修饰属性 2.1当使用final关键字修饰属性,称为常量 2.2变量:存放数据,并且存放的数据是可以发生改变 常量:存放数据,并且存放的数据是不可以发生改变 2.3常量只有两种赋值方式: 第一种方式:在声明同时赋值 final static String name = null; 第二种方式:通过构造方法完成赋值 2.4一般final关键字与static关键字配合使用,原因:节省空间 2.5常量名建议全部大写,如果有多个单词之间使用下划线隔开 比如:数学中的π表示3.1415926 这个值固定的不变的,则在Java中建议编写为常量,一般使用PI表示Java中的π
-
final 关键字修饰方法
- 当使用final 关键字修饰方法,表示该方法是最终的,也就是:该方法不能被重写
7. 多态
- 多态的语法格式
父类类型 引用名 = new 子类();
注意:当前构成多态,引用名称是父类类型,父类中存放的是多个类中公共的属性和方法
也就是说:引用名只能访问父类中公共的属性和方法,但是优先访问当前存放子类对象中重写以后的方法
- 什么是多态
多种不同的形态(结果)
多个对象调用同一个方法,得到多个不同的结果,原因:优先调用子类重写以后的方法
在现实生活中多态的案例,比如:理发师、裁缝、医生 ......都使用剪刀进行剪,得到不同的结果,比如:理发师剪头发,裁缝剪衣服,医生做手术......
- 满足多态的条件
子类继承父类
必须要在子类中重写父类的方法
父类类型 引用名 = new 子类();
-
多态的好处
减少代码的冗余性(重复性),提高代码复用 -
多态中的两种类型转换(重点、难点)
- 当构成多态时,其实也就是向上转型,也叫做自动类型转换
比如:Pet p = new Cat();
也就是:由子到父
当构成多态或者向上转型时,引用名是父类类型
因此:只能访问父类中公共的属性和公共的方法,但是优先访问子类重写以后的方法
当进行向下转型或者强制类型转换时,可能会出现类型转换异常
原因:
当前引用名中存放哪个子类对象,则就只能哪个子类类型,如果非要转换为其他的子类类型,则就出现类型转换异常
解决办法:
在进行向下转型或者强制类型转换之前,建议先判断,如果满足则再向下转型或者强制类型转换
8. 提取方法
其实再IDEA中,也可以再main 方法中编写该题所有功能,然后将单独某个功能选中提取方法
提取方法操作步骤:
第一步:选中某一段单独功能的代码
第二步:按ctrl + alt + m
其中M表示Method方法
9. 抽象类和抽象方法(重点)
-
抽象类
-
再Java中,类就是抽象的,也就是:不是具体的
对象:具体的实例
-
当创建宠物父类对象时,并没有明确得到的是猫对象,还是狗对象…
因此宠物是父类,范围相对比较大,则就可以将父类编写为抽象类
-
什么时候将类编写为抽象类?
建议:将父类编写为抽象类,因为该类范围比较大,一般都创建子类对象;
-
抽象类特点:
- 抽象类使用abstract关键字,其中abstract 表示抽象
- 抽象类是不能创建对象,因此得到:抽象类也是多态的一种形式
-
-
抽象方法
-
不同宠物吃的东西不一样,因此:也就是需要子类重写吃的方法
-
当创建子类对象时,再调用吃eat方法时,会优先调用子类重写以后的方法
也就是:父类Pet中eat方法体使用不到,则就可以将父类中的方法编写为抽象方法 -
什么时候将方法编写为抽象方法?
当父类中的方法体,如果再子类中使用不到,则就可以将父类中的方法编写为抽象方法 -
抽象方法的特点:
4.1抽象方法使用abstract关键字
4.2抽象方法必须没有方法体,也就是:不需要编写大括号,直接以英文分号作为结尾
4.3抽象方法必须在抽象类中
4.4子类继承抽象类时必须要重写抽象类中所有的抽象方法,否则子类也是抽象类
大多数情况下,子类都会重写抽象类中所有的抽象方法
4.5抽象类不能创建对象,也就是说:创建子类对象,因此得到抽象类也是多态的一种形式
-
10. 接口(重点)
- 假如一个类中只编写抽象方法,具体如下:
public abstract class Pet{
public abstract void eat();
}
- 则就可以使用接口完成
-
接口的说明
-
接口使用interface关键字
-
接口中的抽象方法默认有 public abstract
-
再Java中,类与类之间是继承,也就是:子类继承extends父类,并且是单继承
再Java中,接口与类之间是实现,也就是:实现类实现implements 接口,并且是多实现 -
当实现类实现接口时,必须重写接口中所有的抽象方法,否则实现类也是抽象类
大多数实现类都重写接口中所有的抽象方法 -
接口不能创建对象,也就是:接口也是多态的一种形式,也就是创建实现类对象
-
接口也属于引用数据类型,在内存中存放的是地址(引用)
接口
-
public interface Pet{
void eat();
}
- 接口注意事项
-
接口就是功能的封装
例如:一个软件工程师既会编写代码,也会讲业务 -
再JDK8.0 中,接口中包含:
抽象方法(默认有 public abstract )
公有静态常量(默认有public static final)
public static 修饰的方法
public default 修饰的方法 -
在Java中,类与类之间是继承,也就是:子类继承父类,并且是单继承
class A{ } class B extends A{ }
在Java中,接口和接口之间是继承,也就是:子接口继承父接口,并且多继承
interface X{ } interface Y{ } interface Z extends X,Y{ }
在Java中,类和接口是实现,也就是:实现类实现接口,并且是多实现
interface A1{ } interface B1{ } class C1 implements A1,B1{ } //但是接口不能继承类
-
在一个类中,如果既有继承也有实现,则继承必须位于实现的前面
public class ** extends ** implements **,**{ // }
-
抽象类与接口异同点
-
相同点
-
抽象类和接口中都可以编写抽象方法
-
子类或实现类必须要重写抽象类或接口中所有的抽象方法,否则子类或实现类也是抽象类
-
抽象类和接口都不能创建对象,也就是说:抽象类和接口都是多态的一种形式,创建子类对象或者实现类对象
-
-
不同点
Ø 抽象类
-
使用abstract关键字
-
抽象类中包含:普通类中包含的所有内容,也可以包含抽象方法
-
子类继承抽象类,并且是单继承
Ø 接口
-
使用interface关键字
-
在JDK8.0中, 接口中包含:
抽象方法(默认有public abstract)、
公有静态常量(public static final)、
public static修饰的方法、
public default修饰的方法 -
实现类实现接口,并且是多实现
-
-
11. 内部类
-
什么是内部类?
Ø 在一个类中再编写一个类,里面的这个类,称为内部类也叫做内置类或者叫做嵌套类 -
什么时候编写内部类
Ø 一般内部类是对外部类提供服务,如果还想对其他外部类提供服务,则不建议编写内部类
Ø 当一个大的数据结构中包含若干个小的数据结构,则就可以将这些小的数据结构编写为内部类
n 比如:电脑中包含:内存条、硬盘、主板、CPU、风扇………
-
内部类的分类
成员内部类
静态内部类
局部内部类public class MyClass { //编写实例方法 public void print(){ Inner i = new Inner(); } class Inner{ //称为内部类,也叫做成员内部类,一般是在外部类的实例方法中使用 } //编写静态方法 public static void print2(){ Inner2 i = new Inner2(); } static class Inner2{ //称为静态内部类,一般在外部类的静态方法中使用 } public void print3(){ class Inner3{ //局部内部类 } } }
匿名内部类(重点、难点)
-
匿名也就是没有名字
/* 注意:1.什么时候编写为匿名内部类? 当只创建一次对象时,则就可以编写为匿名内部类完成 2.匿名内部类其实也就是对内部类的简写形式 3.编写匿名内部类前提:必须继承父类或者实现接口 */ //Pet pet2 = new Pet(); //注意:出现编译错误,原因:宠物是接口不能创建对象 Pet pet2 = new Pet(){ @Override public void eat() { System.out.println("正在吃......"); } }; pet2.eat();
public class Test2 { public static void main(String[] args) { /*Pet p = new Dog(); p.eat();*/ //其实上面两条语句也可以编写为一条语句完成,具体如下: new Dog().eat(); //注意:当只创建一次对象,则也可以编写为匿名内部类完成 new Pet(){ @Override public void eat() { System.out.println("正在吃Xxxxx"); } }.eat(); } }
-
12. Object类(重点)
- Object类说明
Ø 在Java中,Object类是所有类的父类也叫做超类,要么直接继承Object类,要么间接继承Object类
Ø 当一个类没有使用extends指定继承哪个父类时,则系统默认继承Object类,也就是说:当继承Object父类时,extends Object是可有可无的
Ø 在java中,类具有传递性,也就是说:其实所有类都继承Object类中的方法
Ø API:Java帮助文档
-
常用方法(重点)
- toString()方法
public class Test { public static void main(String[] args) { //创建电脑对象 Computer c = new Computer(); /* 通过运行得到: 1.在默认情况下,只输出引用名(或者叫做对象名)c则输出:com.bjpowernode.demo8.Computer@4554617c 也就是说输出:完整类名@十六进制值 2.原因: 在默认情况下,当只输出引用名时,系统默认调用toString()方法,输出c其实等价于c.toString() 当前引用名c是Computer类型,也就是调用toString()方法时,先在电脑类中找toString(),如果没有找到该方法,则再去父类Object中找toString()方法, 父类的方法体 return getClass().getName() + "@" + Integer.toHexString(hashCode()); 因此得到:默认情况下,只输出引用名,其他调用的是Object类中的toString()方法 输出完整类名@十六进制值 */ System.out.println(c.toString()); //其实等价于c /*3.练习:当创建电脑对象后,只输出对象时要求输出该对象所有实例变量的值 4.解决办法:调用toString() 父类Object中的toString()不能满足子类的要求,因此需要在子类中重写父类的toString()方法 重写方式如下: 第一种方式:光标放在子类中,按Ctrl + O选择父类中要重写的方法,然后按回车键,该方法体中默认调用的是父类中的方法,则需要手动编写代码实现相应功能,一般不常用 第二种方式:光标放在子类中,按Alt + Insert键,选择toString()方法,按回车键,比较常用 5.重写toString()后,也就是将之前编写的print方法实现输出对象所有实例变量的值改为重写toString()*/ c = new Computer("Lenovo", "黑色", 5688, 15.6); System.out.println(c); //其实等价于编写c.toString() } }
//第一种方式:光标放在子类中,按Ctrl + O选择父类中要重写的方法,然后按回车键,该方法体中默认调用的是父类中的方法,则需要手动编写代码实现相应功能,一般不常用
/*@Override
public String toString() {
return "品牌:" + this.brand + ",颜色: " + this.color + ",价格:" + this.price + ",尺寸: " + this.size;
}*/
@Override
public String toString() {
return "Computer{" +
"brand='" + brand + '\'' +
", color='" + color + '\'' +
", price=" + price +
", size=" + size +
'}';
}
- equals(Objectobj)
public class Test {
public static void main(String[] args) {
Person p1 = new Person("张三", 19, '男');
Person p2 = new Person("张三", 19, '男');
System.out.println(p1 == p2); //false 引用数据类型,使用==比较的是内存地址是否一致
Person p3 = p1; //将p1赋给p3,也就是说:p1和p3存放同一个地址,指向同一个对象
System.out.println(p1 == p3); //true
/*
练习题:比较实现两个对象中各个属性的值是否一致
解决办法:使用equals方法完成
在默认情况下,引用名P1调用eqauls()方法时,先在Person类中找equals()方法,如果没有找到则再去父类Object中找equals方法
也就是说:在默认情况下,调用equals()方法其实执行的是Object类中的equals()方法,但是Object类中的equals()依然比较的是两个对象的内存地址是否一致,也就是:不能满足子类的需要,则需要在子类中重写父类的equals方法
重写方式有两种:
第一种方式:光标放在子类中安Ctrl + O 选择要重写的方法equals(),按回车键,该方法体默认调用的是父类中的方法,也就是:需要手动编写代码实现, 因此第一种方式不常用
第二种方式:光标放在子类中,按Alt + Insert选择第5项,实现比较两个对象中的各个属性的值是否一致,一致返回true,否则返回false
*/
System.out.println(p1.equals(p2));
}
}
13. 类与类之间的语言
- UML :统一建模语言
- 常用的UML图:;类图、用例图、时序图……
- 画UML图所使用的工具:visio 、starUML
- 继承(泛化)
Ø 子类继承父类 或者子接口继承父接口 is a
- 实现
Ø 实现类实现接口
- 依赖
Ø 如果A类中方法的返回值类型、参数列表、局部变量,使用到了B类,则称为A类依赖于B类
- 关联
Ø 如果A类中使用B类定义了成员变量,则称为A类关联B类
- 聚合
Ø 聚合也是关联的一种,如果A类中包含若干个B类,但是A类不能限定B类的生命周期,则称为A类为聚合类
- 组合
Ø 组合也是关联的一种,如果A类中包含若干个B类,但是A类能限定B类的生命周期,则称为A类为组合类
14. 递归(了解)
- 什么是递归?
Ø 在Java中,递归也就是:方法自己调用方法自己,必须满足某个条件程序结束
- 递归实现案例
Ø 使用递归完成,计算n!
public class Test {
/*
编写方法,使用递归完成,计算n!
0! = 1
1! = 1
*/
public static int mul(int n){
//判断形参n的值,如果为0或者为1则返回1
if(n == 0 || n == 1){
return 1;
}
return n * mul(n - 1);//重复调用nul方法
}
public static void main(String[] args) {
System.out.println(Test.mul(3));
}
}