个人主页:Hello Code.
本文专栏:Java零基础指南
更多相关内容请点击前往 Java零基础指南 查看
如有问题,欢迎指正,一起学习~~
文章目录
分类和static
分类思想
- 分类思想
分工协作,专人干专事
- 黑马信息管理系统分类
类名 | 说明 |
---|---|
Student类 | 标准学生类,封装键盘录入的学生信息(id,name,age,birthday) |
StudentDao类 | Dao:(Data Access Object缩写)用于访问存储数据的数组或集合 |
StudentService类 | 用来进行业务逻辑的处理(例如:判读录入的id是否存在) |
StudentController类 | 和用户打交道(接收用户需求,采集用户信息,打印数据到控制台) |
分包思想
- 如果将所有的类文件都放在同一个包下,不利于管理和后期维护
所以,对于不同功能的类文件,可以放在不同的包下进行管理
- 包:本质上就是文件夹
创建包(单级包、多级包)
- 多级包之间使用"."进行分割
- 多级包的定义规范:公司的网站地址翻转(去掉www)
比如:百度的网址为www.baidu.com
后期所定义的包结构就是:com.baidu.其他的包名。
- 包的命名规则:英文字母都是小写
包的定义
- 使用
package
关键字定义包 - 格式:
package 包名;
如果是多级包,中间用"."进行分割
包的注意事项
- package语句必须是程序的第一条可执行代码
- package语句在一个Java文件中只能有一个
- 如果没有package,默认表示无包名
类与类之间的访问
- 同一个包下的访问:不需要导包,直接使用即可
- 不同包下的访问
- import 导包后访问
- 通过全类名(包名+类名)访问
应用场景:多个包下,出现了相同的类名,就可以使用这种方式进行区分
注意事项
import、package、class三个关键字的摆放位置存在顺序关系
- package必须是程序的第一条可执行代码
- import需要写在package下面
- class需要在import下面
黑马信息管理系统
需求说明
- 添加学生:键盘录入学生信息(id,name,age,birthday)
使用数组存储学生信息,要求学生id不能重复 - 删除学生:键盘录入学生的id值,将该学生从数组中移除,如果录入的id不存在,需要重新录入
- 修改学生:键盘录入要修改的学生的id值和修改后的学生信息
将数组中该学生的信息修改,如果录入的id在数组中不存在,需要重新录入 - 查询学生:将数组中存储的所有学生的信息输出到控制台
- 使用分类思想、分包思想完成
环境搭建
- 创建模块:itheima-edu-info-manager
- 创建包、创建类
包 | 存储的类 | 作用 |
---|---|---|
com.itheima.edu.info.manager.domain | Student.java | 封装学生信息 |
com.itheima.edu.info.manager.dao | StudentDao.java | 访问存储数据的数组,进行增删改查(库管) |
com.itheima.edu.info.manager.service | StudentService.java | 业务的逻辑处理(业务员) |
com.itheima.edu.info.manager.controller | StudentController.java | 和用户打交道(客服接待) |
com.itheima.edu.info.manager.entry | InfoManagerEntry.java | 程序的入口类,提供一个main方法 |
思路分析
StudentController(客服接待):
1. 方法中接收用户输入的信息
2. 将学生信息封装为学生对象并传递给StudentService
3. 接收方法的boolean类型返回值,根据结果在控制台打印添加成功/添加失败
StudentService(业务员):
1. 将接收到的学生对象,传递给StudentDao
2. 接收方法的boolean返回值,将结果返还给StudentController
StudentDao(库管):
1. 创建Student学生数组长度为5
2. 将接收到的学生对象添加到数组中
3. 返回是否添加成功的boolean类型值
static关键字
static关键字是静态的意思,修饰符,可以修饰成员变量、成员方法
被static修饰的成员变量,一般叫做静态变量
被static修饰的成员方法,一般叫做静态方法
特点
- 被类所有的对象共享,是我们判断是否使用静态关键字的条件
- 随着类的加载而加载,优先于对象存在,对象需要类被加载后,才能创建
- 可以通过类名调用,也可以通过对象名调用,推荐使用类名调用
注意
- 静态方法中,只能访问静态成员(成员变量、成员方法)
- 静态方法中,没有this关键字
继承
概述
- 继承:让类于类之间产生关系(子父类关系),子类可以直接使用父类中非私有的成员
- 格式:
public class 子类名 extends 父类名{}
- 范例:
public class Zi extends Fu{}
- Fu:是父类,也被称为基类、超类
- Zi:是子类,也被称为派生类
优点
- 提高了代码的复用性
- 提高了代码的维护性
- 让类与类之间产生了关系,是多态的前提
弊端
- 继承是侵入性的
- 降低了代码的灵活性
继承关系,导致子类必须拥有父类非私有属性和方法,让子类自由的世界中多了些约束
- 增强了代码的耦合性
耦合性:代码与代码之间存在的关联都可以称之为“耦合”。
- 应用场景
当类与类之间,存在相同(共性)的内容,并且产生了is a的关系,就可以考虑使用继承,来优化代码 - Java继承的特点
Java只支持单继承,不支持多继承,但支持多层继承
成员特点
成员变量
- 访问特点
- 子类局部范围找
- 子类成员范围找
- 父类成员范围找
- 注意
如果子父类中,出现了重名的成员变量,通过就近原则,会优先使用子类的
如果一定要使用父类的,可以通过super
关键字进行区分
super关键字
super
和this
关键字的用法相似- this:代表本类对象的引用
- super:代表父类存储空间的标识(可以理解为父类对象引用)
成员方法
- 访问特点
- 子类成员范围找
- 父类成员范围找
方法重写
概述:在继承体系中,子类出现了和父类中一模一样的方法声明
应用场景
当子类需要父类的功能,而功能主体子类有自己特有内容,可以重写父类中的方法,这样,既沿袭了父类的功能,又定义了子类特有的内容
区别
方法重写:在继承体系中,子类出现了和父类一模一样的方法声明(方法名,参数列表,返回值类型)
方法重载:在同一个类中,方法名相同,参数列表不同,与返回值无关
注意事项
- 父类中私有方法不能被重写
- 父类静态方法,子类必须通过静态方法进行重写,父类非静态方法,子类也必须通过非静态方法进行重写
静态方法不能被重写!如果子类中,也存在一个方法声明一模一样的方法,可以理解为,子类将父类中同名的方法,隐藏了起来,并非是方法重写!
- 子类重写父类方法时,访问权限必须大于等于父类
权限修饰符
修饰符 | 同一个类中 | 同一个包中子类无关类 | 不同包的子类 | 不同包的无关类 |
---|---|---|---|---|
private | √ | |||
default(默认) | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
构造方法
- 子类中所有的构造方法默认都会访问父类中无参的构造方法
子类在初始化的时候,有可能会使用到父类中的数据,如果父类没有完成初始化,子类将无法使用父类的数据(子类在初始化前,一定要先完成父类的初始化)
- 构造方法的第一条语句默认都是:
super();
- 注意:如果我们编写的类,没有手动指定父类,系统也会自动继承Object(Java继承体系中的最顶层父类)
访问特点
- 如果父类中没有空参构造方法,只有带参构造方法,会出现错误
- 子类通过super,手动调用父类的带参构造方法
注意:this()和super()必须放在构造方法的第一行有效语句,并且二者不能共存
抽象类
入门
- 抽象方法:将共性的行为(方法),抽取到父类之后,发现该方法的实现逻辑无法在父类中给出具体明确,该方法就可以定义为抽象方法。
- 抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类。
定义格式
- 抽象方法:
public abstract 返回值类型 方法名(参数列表);
- 抽象类:
public abstract class 类名{}
注意事项
- 抽象类不能实例化(创建对象)
- 抽象类中有构造方法
- 抽象类的子类
要么重写父类中所有的抽象方法
要么将自己也变成一个抽象类(了解)
- 抽象类中的方法
- 抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
模板设计模式
- 设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。
通俗来说就是写代码的风格
- 模板设计模式:把抽象整体就可以看做成一个模板,模板中不能决定的东西定义成抽象方法
让使用模板的类(继承抽象类的类)去重写抽象方法实现需求 - 优势:模板已经定义了通用结构,使用者只需要关心自己需要实现的功能即可
final关键字
final修饰的特点
- 修饰方法:表明该方法是最终方法,不能被重写
- 修饰变量:表明该变量是常量,不能再次被赋值
常量的命名规范:如果是一个单词,所有字母大写,如果是多个单词,所有字母大写,但是中间需要使用下划线_分隔
修饰基本数据类型变量:其值不能被更改
修饰引用数据类型变量:地址值不能被更改,但是可以修改对象的属性值
final修饰成员变量,需要在创建的时候直接赋值或者在构造方法结束之前完成赋值
- 修饰类:表明该类是最终类,不能被继承
代码块
概述:在Java中,使用{}括起来的代码都被称为代码块
分类
- 局部代码块
- 位置:方法中定义
- 作用:限定变量的生命周期,及早释放,提高内存利用率
- 构造代码块
- 位置:类中方法外定义
- 特点:每次构造方法执行的时候,都会执行该代码块中的代码,并且在构造方法执行前执行
- 作用:将多个构造方法中相同的代码,抽取到构造代码块中,提高代码的复用性
- 静态代码块
- 位置:类中方法外定义
- 特点:需要通过static关键字修饰,随着类的加载而加载,并且只执行一次
- 作用:在类加载的时候做一些数据初始化的操作
接口
概述:当一个类中所有方法都是抽象方法的时候,我们就可以将其定义为接口
接口也是一种引用数据类型,它比抽象类还要抽象
意义
- 规则的定义
- 程序的扩展性
定义和特点
- 使用interface关键字:
public interface 接口名{}
- 接口不能实例化(创建对象)
- 接口和类之间是实现关系,通过implements关键字表示
public class 类名 implements 接口名{}
- 接口的子类(实现类)
要么重写接口中的所有抽象方法
要么是抽象类
- 支持单接口实现,也支持多实现
public class 类名 implements 接口名1,接口名2{}
成员的特点
- 成员变量
只能是常量,系统会默认加入三个关键字:public
、static
、final
- 构造方法
接口中不存在构造方法 - 成员方法
只能是抽象方法(JDK7以前),系统会默认加入两个关键字:public
、abstract
JDK8中接口成员的特点
允许接口中定义非抽象方法,但是需要使用关键字
default
修饰,这些方法就是默认方法定义格式:
public default 返回值类型 方法名(参数列表){}
默认方法不是抽象方法,所以不强制重写,但是可以被重写,重写的时候去掉default关键字
public可以省略,但是default不能省略
如果实现了多个接口,多个接口中存在相同的方法声明,子类就必须对该方法进行重写
JKD9中接口成员的特点
接口中私有方法的定义格式:
private 返回值类型 方法名(参数列表){}
private static 返回值类型 方法名(参数列表){}
使用思路
- 如果发现一个类中所有的方法都是抽象方法,那么就可以将该类,改进为一个接口
- 涉及到了接口大面积更新方法,而不想去修改每一个实现类,就可以将更新的方法,定义为带有方法体的默认方法
- 希望默认方法的调用更加简洁,可以考虑设计为static静态方法(需要去掉default关键字)
- 默认方法中出现了重复的代码,可以考虑抽取出一个私有方法(需要去掉default关键字)
类和接口的关系
- 类和类的关系
继承关系,只能单继承,但是可以多层继承 - 类和接口的关系
实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口 - 接口和接口的关系
继承关系,可以单继承,也可以多继承
多态
概述:同一个对象,在不同时刻表现出来的不同形态
前提
- 要有(继承 \ 实现)关系
- 要有方法重写
- 要有父类引用,指向子类对象
成员访问特点
- 构造方法:同继承一样,子类会通过super访问父类构造方法
- 成员变量:编译看(等号)左边(父类),执行看(等号)右边(父类)
- 成员方法:编译看(等号)左边(父类),执行看(等号)右边(子类)
优劣点
- 好处:提高了程序的扩展性
具体体现:定义方法的时候,使用父类型作为参数,该方法就可以接收这父类的任意子类对象
- 弊端:不能使用子类的特有功能
多态中的转型
- 向上转型
从子到父
父类引用指向子类 - 向下转型
从父到子
父类引用转为子类对象
存在的风险
- 概述:如果被转的引用类型变量,对应的实际类型和目标类型不是同一种类型,那么在转换的时候就会出现ClassCastException
instanceof关键字
- 使用格式:
变量名 instanceof 类型
通俗的理解:判断关键字左边的变量,是否是右边的类型,返回boolean类型结果
内部类
概述:就是在一个类中定义一个类。举例:在A类的内部定义一个B类,B类就被称为内部类
成员内部类
位置:在类的成员位置
创建内部类对象的格式:外部类名.内部类名 对象名 = new 外部类对象(). new 内部类对象()
内部类的访问特点
- 内部类可以直接访问外部类的成员,包括私有
- 外部类要访问内部类的成员,必须创建对象
- 也属于成员,可以被一些修饰符修饰
- private
私有成员内部类访问:在自己所在的外部类中创建对象访问 - static
静态成员内部类访问格式:外部类名.内部类名 对象名 = new 外部类名.内部类名();
静态成员内部类中的静态方法:外部类名.内部类名.方法名();
- private
局部内部类
概述:局部内部类是在方法中定义的类,所以外界无法直接使用,需要在方法内部创建对象并使用,该类可以直接访问外部类的成员,也可以访问方法内的局部变量
位置:类的局部位置
匿名内部类
概述:本质上是一个特殊的局部内部类(定义在方法内部)[使用次数远远大于成员内部类和局部内部类]
前提:需要存在一个接口或类
格式
new 类名或者接口名(){
重写方法;
}
理解:将继承\实现,方法重写,创建对象三个步骤放在了一步进行
使用场景
当方法的形式参数是接口或者抽象类时,可以将匿名内部类作为实际参数进行传递
Lamdba表达式
理解:对于Lambda表达式,是对匿名内部类进行了优化,代码更少,关注点更加明确
函数式编程思想概述
在数学中,函数就是有输入量、输出量的一套计算方案,也就是“拿数据做操作”
面向对象思想强调“必须通过对象的形式来做事情”
函数式思想则尽量忽略面向对象的复杂语法:“强调做什么,而不是以什么形式去做”
而我们要学习的Lambda表达式就是函数式思想的体现
标准格式
- 格式:
(形式参数) -> {代码块}
- 形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
->
:由英文中画线和大于符号组成,固定写法,代表指向动作- 代码块:是我们具体要做的事情,也就是以前写的方法体内容
使用前提
- 有一个接口
- 接口中有且仅有一个抽象方法
练习
// 1.编写一个接口(ShowHandler)
// 2.在该接口中存在一个抽象方法(show),该方法是无参数无返回值
// 3.在测试类(ShowHandlerDemo)中存在一个方法(useShowHandler)
// 方法的参数是ShowHandler类型的
// 在方法内部调用了ShowHandler的show方法
public class TestLambda{
public static void main(String[] args){
// 匿名内部类实现
useShowHandler(new ShowHandler(){
@Override
public void show(){
System.out.println("我是匿名内部类中的show方法");
}
});
// Lambda实现
useShowHandler(() -> {
System.out.println("我是匿名内部类中的show方法");});
}
public static void useShowHandler(ShowHandler showHandler){
showHandler.show();
}
}
interface ShowHandler{
void show();
}
// 1.首先存在一个接口(StringHandler)
// 2.在该接口中存在一个抽象方法(printMessage),该方法是有参数无返回值
// 3.在测试类(StringHandlerDemo)中存在一个方法(useStringHandler),方法的参数是StringHandler类型的,在方法内部调用了StringHandler的printMessage方法
public class StringHandlerDemo{
public static void main(String[] args){
// 匿名内部类实现
useStringHandler(new StringHandler(){
@Override
public void printMessage(String msg){
System.out.println("我是匿名内部类." + msg);
}
});
// Lambda实现
useStringHandler((String msg) -> {
System.out.println("我是Lambda" + msg);});
}
public static void useStringHandler(StringHandler stringHandler){
stringHandler.printMessage("坚持学习!");
}
}
interface StringHandler{
void printMessage(String msg);
}
省略规则
- 参数类型可以省略,但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,甚至是return
Lambda表达式和匿名内部类的区别:
所需类型不同
- 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
- Lambda:只能是接口
使用限制不同
- 如果接口中有且仅有一个抽象方法,可以使用Lambda表达式,也可以使用匿名内部类
- 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
实现原理不同
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- Lambda表达式:编译之后,没有一个单独的.class字节码文件,对应的字节码会在运行的时候动态生成
推荐阅读:Java常用API&异常