java,从入土到出棺——3.逻辑结构与程序控制
写在前面:
其实这个系列的文章更加偏向于总结向,是对以往一些知识做个系统的总结,也是为已经有一定基础的人铺路,提供一个系统的思考。
对新人可能是很不友好的,可能有些人是刚接触,上来就是组合代理的,建议新人上网先做个学习,再把我这个对比记忆,说不定还能发现我的错误呢,说不准哦,三人行,必有我师;如果想和我讨论的,可以直接留言,也可以和我私信,我会很乐意和大家来讨论的。
同时也请大佬们不吝赐教!
1 逻辑结构
1.1 概述
逻辑结构分为业务逻辑结构(又称系统逻辑结构)和数据逻辑结构:
业务逻辑结构是对整个整个业务进行细分,把一整套的产品分成若干个业务逻辑单元,分别实现自己的功能。一般在系统开发时,业务逻辑结构往往都由架构师完成。业务逻辑结构对系统的开发起到重要性的决定,可以说是产品的灵魂。
数据逻辑结构是对数据之间关系的描述,有时就把数据逻辑结构简称为数据结构。数据结构是计算机存储、组织数据的方式。这里有两个重点,一个是储存:毕竟我们计算机如果存储不了数据,那也只是个一次性的物件,每次运算都去去源重新调用,计算的结果在没法重复使用,就无法进行复杂的计算;另一个是组织:通过内在的逻辑将数据有序(并不只是常识认知上的有序)地存放,以便后期取用时可以更高效,对算法提供大力的支持。
关于数据结构的总结已经在上一篇文章:《java,从入土到出棺——2.数据结构(从容器(集合等)到底层原理)》进行了详细的汇总,本文主要来讲述另外一种逻辑结构:业务逻辑结构。
1.2 业务逻辑结构的“五常”
1.2.1 控制——调度者
根据数据采集者所传入的参数进行不同的功能分配,实现不同功能与不同参数的调度,是整个逻辑的领导者。
1.2.2 处理——业务处理
根据不同的业务进行逻辑运算与数据处理,对调度者所传入的数据进行加工,加工成适合数据库可以储存的消息类型,是整个业务逻辑结构中的核心。
1.2.3 储存——数据的时效储存
储存所有处理过后的资源,可以进行临时性或者永久性储存,并且在业务需要的时候可以随时取出,是整个业务的大仓库。
1.2.4 输入——数据的获取
前端对于后端的数据传递,并将之交给调度者进行分配
1.2.5 输出——数据的处理反馈
对于前端的请求,经过所有的业务逻辑处理之后,给其的反馈,是整个业务处理的成果,也是使用者所需要的数据。
2 程序控制结构
程序控制结构主要是“五常”中的处理功能,前端所需要的结果却是各种各样的,因此,需要不同的业务处理方式来进行操作,这就需要程序控制结构来进行不同逻辑的体现。
理论和实践证明,无论多复杂的算法均可通过顺序、选择、循环3种基本控制结构构造出来。每种结构仅有一个入口和出口。
2.1 顺序结构
顺序结构是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行的。
顺序结构执行流程图:
2.2 选择结构
2.2.1 逻辑判断
在数学中,一个数据x,大于3,小于6,我们可以这样来进行表示:3 < x < 6;而在计算机语言中,需要把上面的式子先进行拆解,再进行合并表达。
拆解为:x>3 和 x<6;合并后:x>3 & x<6
&其实就是一个逻辑运算符。我们可以这样说,逻辑运算符,是用来连接关系表达式的运算符。当然,逻辑运算符也可以直接连接布尔类型的常量或者变量。
分类
种类 | 符号 | 作用 | 说明 |
---|---|---|---|
基础逻辑运算符 | & | 逻辑与, 和,并且 | a&b,a和b都是true,结果为true,否则为false |
基础逻辑运算符 | | | 逻辑或 | a|b,a和b都是false,结果为false,否则为true |
基础逻辑运算符 | ^ | 逻辑异或 | a^b,a和b结果不同为true,相同为false |
基础逻辑运算符 | ! | 逻辑非 | !a,结果和a的结果正好相反 |
短路逻辑运算符 | && | 短路与 | 作用和&相同,但是有短路效果 |
短路逻辑运算符 | || | 短路或 | 作用和|相同,但是有短路效果 |
注意事项
- 逻辑与 & ,无论左边真假,右边都要执行;
- 短路与 &&,如果左边为真,右边执行;如果左边为假,右边不执行。
- 逻辑或 |,无论左边真假,右边都要执行;
- 短路或 ||,如果左边为假,右边执行;如果左边为真,右边不执行
其中最为常用的是“&&”、“||”和“!”。
2.2.2 if语句
①单路分支
执行流程
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体
③如果关系表达式的值为false就不执行语句体
④继续执行后面的语句内容
格式
if (比较表达式) {
语句体;
}
执行流程图
(太过简单,仅总结,不做代码演示)
②两路分支
执行流程
①首先计算关系表达式的值
②如果关系表达式的值为true就执行语句体1
③如果关系表达式的值为false就执行语句体2
④继续执行后面的语句内容
格式
if (关系表达式) {
语句体1;
} else {
语句体2;
}
执行流程图
(太过简单,仅总结,不做代码演示)
思考:两路分支时,if与三元运算谁的效率更高效?
这个主要与三元运算符的规则有关,三元运算符的转换规则:
- 若两个操作数不可转换,则不做转换,返回值为Object类型
- 若两个操作数是明确类型的表达式(比如变量),则按照正常的二进制数字来转换,int类型转换为long类型,long类型转换为float类型等。
- 若两个操作数中有一个是数字S,另外一个是表达式,且其类型标示为T,那么,若数字S在T的范围内,则转换为T类型;若S超出了T类型的范围,则T转换为S类型。
- 若两个操作数都是直接量数字,则返回值类型为范围较大者。
但是大家可以实验一下,if与三元运算两者所耗费时间其实是相差不多的,但是三元运算的代码是很美观和简洁的,可读性也较强。
使用三元运算符是先运算的,所以可以避免使用if语句时候出现的分支预判错误的情况发生,而 if 语句是直接赋值 ,不存在运算,所以快了一点(也仅仅是一点,其实差不太多)。
结论
- 三元运算是必须要有返回值,而if-else语句并不一定有返回值,其执行结果可能是赋值语句或者打印输出语句;如果不涉及返回值的需求情况,三元运算是首选;其余情况if-else更易于使用和理解;
- java三元运算字符强转(双目数值提升)的功能,返回值类型为两个返回值中类型精度更高的的那个类型,所以在特殊情况下,用三元运算更方便。
③多路分支
执行流程
①首先计算关系表达式1的值
②如果值为true就执行语句体1;如果值为false就计算关系表达式2的值
③如果值为true就执行语句体2;如果值为false就计算关系表达式3的值
④…
⑤如果没有任何关系表达式为true,就执行语句体n+1
格式
if (关系表达式) {
语句体1;
} else if {
语句体2;
} else if {
······
} else {
语句体n + 1;
}
执行流程图
(太过简单,仅总结,不做代码演示)
2.2.3 switch语句
执行流程
①将要匹配的值,,与case给出的值, 逐个进行匹配(从上到下)
②如果匹配成功,则执行对应的语句体,,然后由break语句结束掉整个switch语句
③如果所有的case全部匹配失败,将会执行default语句当中的语句体,然后由break结束switch
格式
// 将要匹配的值 : 可以是一个常量, 也可以是变量(常用的方式)
switch(将要匹配的值) {
case 值1:
语句体1;
break;
case 值2:
语句体2;
break;
...
default:
语句体n+1;
break;
}
特别注意
- case后面的值只能是常量,不能是变量;
- case后面的值不允许重复定义;
- break语句可以省略,但会出现case穿透的现象;
- default语句可以省略,但是不建议,因为需要default对范围外的错误值,给出提示;
- 表达式(将要匹配的值)可以接受的类型为基本数据类型(byte short char (int) -> 只要是能够提升为int类型的)和引用数据类型(jdk1.5之后可以接收枚举,jdk1.7之后可以接收(String字符串))。
2.2.4 switch与if的选择
switch与if各有各的应用环境,通常:switch主要用于匹配一个值,if 可以用来匹配一个值, 也可以用匹配区间范围。
但是,当两者都可以使用的时候,我们需要了解一下他们的优缺点,才可以根据需要去选择不同的用法。这里我们需要查看他们的汇编指令来分析,过程我就不在这个整理的文章的说了(如果感兴趣的人比较多,后期我可以出一篇文章专门讲这个),直接展示结论:switch与if的根本区别在于,switch中,每个case会生成一个地址,并且可以根据索引(switch传入值)直接指向相应的地址。而if是顺序遍历条件,直到命中。 所以switch是用一定的内存空间来节约了查询时间。
- 在多路分支时,switch比if结构要效率高;
- 当case常量分布范围很大但实际有效值又比较少的情况,switch的空间利用率将变得很低;
- switch只能处理分支为常量的情况:但是像 ( x > 1 (x > 1 (x>1 && x < 10 ) x < 10) x<10) 的非常量处理能力有限。所以,switch在常量选择分支时比if效率高,但是if能应用于更多的场合,比较灵活。
代码写的复杂,让人看不懂,不NB;代码写的简洁,又能实现功能,才NB😀😀😀😀
2.3 循环结构
2.3.1 for
执行流程
①执行初始化语句
②执行条件判断语句,看其结果是true还是false
如果是false,循环结束
如果是true,继续执行
③执行循环体语句
④执行条件控制语句
⑤回到②继续
格式
for (初始化语句;条件判断语句;条件控制语句) {
循环体语句;
}
/*
* 初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
* 条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
* 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
* 条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去
*/
2.3.2 while
执行流程(与for相同)
①执行初始化语句
②执行条件判断语句,看其结果是true还是false
如果是false,循环结束
如果是true,继续执行
③执行循环体语句
④执行条件控制语句
⑤回到②继续
格式
初始化语句;
while (条件判断语句) {
循环体语句;
条件控制语句;
}
/*
* 初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
* 条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
* 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
* 条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去
*/
2.3.3 do-while
执行流程
① 执行初始化语句
② 执行循环体语句
③ 执行条件控制语句
④ 执行条件判断语句,看其结果是true还是false
如果是false,循环结束
如果是true,继续执行
⑤ 回到②继续
格式
初始化语句;
do {
循环体语句;
条件控制语句;
}while(条件判断语句);
/*
* 初始化语句: 用于表示循环开启时的起始状态,简单说就是循环开始的时候什么样
* 条件判断语句:用于表示循环反复执行的条件,简单说就是判断循环是否能一直执行下去
* 循环体语句: 用于表示循环反复执行的内容,简单说就是循环反复执行的事情
* 条件控制语句:用于表示循环执行中每次变化的内容,简单说就是控制循环是否能执行下去
*/
2.3.4 三种循环的区别与选择
- for循环和while循环先判断条件是否成立,然后决定是否执行循环体(先判断后执行)
- do…while循环先执行一次循环体,然后判断条件是否成立,是否继续执行循环体(先执行后判断)
for循环和while的区别:
- 条件控制语句所控制的自增变量,因为归属for循环的语法结构中,在for循环结束后,就不能再次被访问到了
- 条件控制语句所控制的自增变量,对于while循环来说不归属其语法结构中,在while循环结束后,该变量还可以继续使用
思考:for和while使用哪一个?
- 如果明确循环次数, 使用for循环
- 如果不明确循环次数, 使用while循环
PS
鉴于前两篇写的有点儿偏底层,所以这一篇总结一篇较为简单且非常容易理解的,但其实重点并不是程序控制结构,而是逻辑结构,万事代码为后,业务为先!!
有不了解的先动手自己查查,实在不明白了来问我,不是装13,而是这样大家自己搜索只是并且整合知识的能力才会增强,我是真的不支持白嫖,原因就是这会影响大家的学习态度,不过来问我我是来者不拒的。😄😄
再次谢谢大家支持!!!
来源:oschina
链接:https://my.oschina.net/u/4262172/blog/4689063