通过语句控制Java程序
顺序结构
从上往下由左往右依次编译执行(绝大部分代码)
分支结构
if语句(判断结构)
从上往下由左往右依次编译执行(绝大部分代码)
1.格式一:
if语句格式1(提供一个选择,可能有结果可能没有结果)
if(判断条件){
语句体;
}
执行流程
先去计算判断条件,如果判断条件计算之后的值为true接着执行语句体执行完语句体之后执行其他语句;如果判断条件计算之后的值为false执行其他语句。
2.格式二:
if语句格式2(提供一个选择,提供一个选择,一定返回一个结果)
if(判断条件){
语句体1;
}else{
语句体2;}
执行流程
先去计算判断条件的值,如果判断条件的值计算出之后是true执行语句体1接着执行其他语句;如果判断条件的值计算出之后是false执行语句体2接着执行其他语句。
注:
if语句格式2的语句体是值时才和三目等效
3.格式三:
if语句格式3(提供多个选择,只有一个结果)
if(判断条件1){
语句体1;
}else if(判断条件2){
语句体2;
}else if(判断条件3){
语句体3;
}
…
else{
语句体n+1;
}
执行流程
先去计算判断条件1,如果值是true执行语句体1接着执行其他语句;如果值是false接着计算判断条件2,如果值是true执行语句体2接着执行其他语句;如果值是false接着计算判断条件3如果计算结果是true执行语句体3接着其他语句;如果一直计算判断条件的值都是false执行else里的语句体n+1接着执行其他语句。
switch语句(选择结构)
1.格式:
switch(表达式){
case值1:
语句体1;
break;
case值2:
语句体2;
break;
case值3:
语句体2;
break;
…
default:
语句体n+1;
break;
}
执行流程
先去计算出表达式的值,拿着这个计算出的值和所有的case值进行比较如果有相等的就执行对应case的语句体,执行完语句体执行break,switch语句执行结束;如果计算出的值和所有的case值都不相等执行default对应的语句体接着执行break,switch语句结束。
注:
1.表达式支持byte、short、int、char,从jdk1.5开始支持枚举类型、从jdk1.7开始支持String类型。
2.case的值都是常量,不能重复。
3.支持省略break,省略break会出现case穿透效果(给定月份返回对应的季节 )。
4.支持省略default(选择题 机考)。
5.switch语句结束的标志:
1)遇见break; 2)执行到代码最后一行自然结束。
if和switch比较:
如果判断内容是一个范围推荐使用if
如果判断内容是值推荐使用switch循环结构
循环结构
要素
定义循环变量
控制循环条件
改变循环变量
1、for语句
for循环(循环范围确定)
1)格式
for(初始值;判断条件;控制条件){
循环体;
}
2)执行流程
根据初始值和判断条件进行比较,如果比较的结果是true执行循环体,执行控制条件改变初始化值,拿着改变的值再和判断条件进行比较,如果比较的结果是true重复上述操作直到比较的结果是false才结束循环。
2、while语句
while循环(循环范围不确定)
1)格式
初始化值;
while(判断条件){
循环体;
控制条件;
}
2 )执行流程
根据初始值和判断条件进行比较,如果比较的结果是true执行循环体,执行控制条件改变初始化值,拿着改变的值再和判断条件进行比较,如果比较的结果是true重复上述操作直到比较的结果是false才结束循环。
3、do-while语句
dowhile循环(最少执行一次)
1)格式
初始值;
do{
循环体;
控制条件;
}while(判断条件);
2)执行流程
先获取初始化值接着执行循环体接着执行控制条件改变初始值,拿着改变的初始值和判断条件进行比较,如果比较的结果是true执行循环体执行控制条件改变初始值拿着改变的初始值和判断条件进行比较如果比较的结果是true重复上述操作直到比较的结果为false结束循环。
4、三种循环语句的区别和联系
1.三种循环等效转换
2.for循环的初始值不能在后续使用
3.三种循环都有可能出现死循环
5、控制跳转语句
1、break—跳出当前循环不执行(可用于选择结构和循环结构中)
2、continue—跳出当次循环(只能用于循环结构)
也可 标号 循环:名称;
out:for(int i=1;i<=3;i++){
in:for(int j=1;j<=4;j++){
if(j==2){
break in;
}
}
3、return—在方法中返回返回值、结束本方法
数组
1、概念
存储多个相同类型元素的容器
2、定义
1、数组类型[] 数组名=new 数据类型[数组长度/元素个数];—(指定长度)
支持分为声明和初始化两个过程
通过数组得地址值可以找到对应的数组容器,数组内部自动对存储的元素进行编号(从0开始),通过数组地址值和元素编号就可以唯一确定数组中的元素—数组名[编号](编号—下标)
2、数组类型[] 数组名=new 数据类型[]{元素值1,元素值2,…};(给定元素值,长度已经确定,前面不能在指定长度值)
3、数组类型[] 数组名={元素值1,元素值2,…};(给定元素值,长度已经确定,不支持初始化-----底层没有开辟空间所以不能存储数据)
3、new关键字
在堆内存开辟新空间(数组是存放在堆内存中,会默认初始值)(栈内存存储的是这个数组的地址)
编译运行:int[] a =new int[5];System.out.println(a);
结果:[I@659e0bfd
[:当前部分代表对象类型,内容是[代表当前的对象类型是数组。
I:当前这个部分代表元素的类型,内容I代表元素类型是int类型。
@:代表后面区域的内容是地址。
659e0bfd:数据内存地址值—十六进制的哈希码值。
4、java内存分区
1)栈
存储变量(暂时),栈中存储的数据使用完毕时立刻销毁
2)堆
存储对象,存储的对象如果不再使用,会在某个时刻通过系统进行回收
3)方法区
存储的类的信息
在静态区会给静态变量给定系统默认初始值
4)本地方法栈
本地(操作系统)方法
5)寄存器(PC计数器)
表示代码执行的指令
5、系统默认初始值
(byte、short、int—0)
(char—’\u0000’ \u代表编码使用的码表是utf-16)
(long—0L)
(float—0.0F)
(double—0.0)
(boolean—false)
(所有引用类数据型—null)
栈和堆
系统默认初始值先于程序初始值给值(在堆中)
多个引用指向同一个数组—共享
eg:
int [] a1=new int[3];
a1[0]=10;
int [] a2=new int[]{3,4};
a2[1]=10;
int [] a3=a1;
a3[0]=100;
System.out.println(a1[0]); //值为100
6、数组的应用
1、遍历
依次输出数组元素值 数组名[下标]----确定任意数组元素
①普通for循环
功能:数据操作
②增强for循环
格式:(元素类型 变量名:遍历的数组的名称)
原理:把数组元素的值拷贝到变量身上
功能:只能遍历
③Arrays
自动把数组元素内容进行拼接,拼接成一个字符串输出(展示结果)
System.out.println(Arrays.toString(arr));
功能:数组展示
4)遍历例题:求最值
根据参照物来比较最大值/最小值
2、查找
指定一个数,根据这个数返回第一次出现的数组元素的下标
1)查找例题:二分查找法
时间复杂度o(logn)
空间复杂度o(l)
缺点:有序、查找数靠前
优点:效率高
中心思想:
//定义三个下标用变量来表示
int min=0;
int max=arr.length-1;//长度值-1
int mid=(min+max)/2;
//循环--while
while(num!=arr[mid]){//中间下标对应的元素值不相等才进循环操作
//如果查找数大于中间下标对应的元素值
if(num>arr[mid]){
//把最小下标往右挪动
min=mid+1;
}
//如果查找数小于中间下标对应的元素值
if(num<arr[mid]){
//把最大下标往左挪动
max=mid-1;
}
//查找数不存在情况
if(min>max){
System.out.println("查无此数");
break;
}
//重新计算中间下标
mid=(min+max)/2;
}
//
if(max>=min)
System.out.println(mid);
3、排序
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
1)冒泡排序
相邻两个元素进行比较,一轮比较完得到一个最大值
时间复杂度o(n^2)
空间复杂度o(l)
import java.util.Arrays;
class ArrayMaoDemo{
public static void main(String[] args) {
//无序数组
int[] arr={8,5,9,7,6,2};
//通过嵌套循环实现冒泡排序
for(int i=1;i<=arr.length;i++){//外层循环---控制轮数
for(int j=1;j<=arr.length-i;j++){//内层循环---控制参与比较的元素范围
//相邻两个元素进行比较 j-1 j j j+1(两组都可以选择需要改动j的取值范围)
if(arr[j-1]>arr[j]){//升序---如果前面的值大于后面的值需要交换
//交换两个整数值
int temp=arr[j-1];
arr[j-1]=arr[j];
arr[j]=temp;
}
}
}
//输出数组
System.out.println(Arrays.toString(arr));
}
}
2)选择排序
选择一个定点和后续其它元素进行比较,一轮比完得到一个最小值
时间复杂度o(n^2)
空间复杂度o(l)
import java.util.Arrays;
class ArrayMaoDemo{
import java.util.Arrays;
class ArrayMaoDemo{
public static void main(String[] args) {
//无序数组
int[] arr={8,5,9,7,6,2};
//通过嵌套循环实现冒泡排序
for(int i=1;i<arr.length;i++){//外层循环---控制轮数
for(int j=1;j<arr.length;j++){//内层循环---控制参与比较的元素范围
//选择一轮中不动的下标和后续所有的元素进行比较
if(arr[i-1]>arr[j]){//升序---如果前面的值大于后面的值需要交换
int temp=arr[i-1];
arr[i-1]=arr[j];
arr[j]=temp;
}
}
}
//输出数组
System.out.println(Arrays.toString(arr));
}
}
总
Arrays.sort()----底层提供了很多排序算法
时间复杂度o(nlogn)
4、扩容
扩大/小数组容器的容量(长度)—数组复制实现—数组定义完成之后长度无法改变。
数组的扩容之后的地址一定发生了改变
//给定原数组
int[] arr1={1,3,4,6,2};
//Arrays.copyOf(原数组,变化之后的长度)
arr1=Arrays.copyOf(arr1,arr1.length-1);
System.out.println(Arrays.toString(arr1));
该方法使用不方便,但复制元素内容比较灵活
基本原理
//给定原数组
int[] arr1={1,3,4,6,2};
//新数组
int[] arr2=new int[arr1.length*2];//确定新长度
//数组的复制(原数组,拷贝的起始下标,目标数组,粘贴的起始下标,复制的元素个数)
System.arraycopy(arr1,0,arr2,0,arr1.length);
//数组地址值的赋值
arr1=arr2;
从头复制,书写方便
时间复杂度和空间复杂度
时间复杂度:程序中必然会执行的代码的执行时间认为是单位1,执行这个单位1所需要的次数
空间复杂度:程序执行过程中,额外开辟的内存空间。
二维数组
1、概念
存储的数组元素是一维数组的数组
2、定义格式
1、数据类型[][] 数组名=new 数据类型[二维数组长度][一维数组长度];
2、数据类型[][] 数组名=new 数据类型[二维数组长度][];
3、数据类型[][] 数组名={{元素值1,元素值2,…},{元素值1,元素值2,…},{元素值1,元素值2,…},…};
二维数组的内存
1、二维数组存放在堆内存中
2、二维数组的每一个位置上存储的是一维数组的地址
3、如果一个位置上没有指定一维数组,那么默认值为null。
方法
由方法名和参数列表共同决定的方法才是唯一确定的方法
方法是由方法签名来区分(方法签名由方法名和参数列表共同决定)
1、概念
把重复且有效的代码抽取的形式
2、书写格式
修饰符 方法返回值类型 方法名(参数类型1 参数值1,参数类2 参数值2,…){
方法体;
return 返回值;
}
1)修饰符
public static
2)方法返回值类型
1、根据方法的返回值的数据类型提供对应的数据类型来接收方法返回值。
2、方法可能没有返回值指定void来表示没有返回值
3)方法名
标识符
4)参数列表
由参数类型、参数个数、参数顺序共同决定
5)方法体
重复且有效的代码
6)return
把方法的返回值进行返回,跳出方法
7)调用方法
public static void printXing(int m,int n){}
①单独调用(执行方法)
方法名(参数值)
eg:printXing(6,7);
②输出调用
把方法返回值进行输出
eg:System.out.println(sum(2,3));
③赋值调用
把方法返回值赋值给新变量
eg:int x=sum(2,3);
3、注意
1、方法一定要被调用才能执行(方法不主动执行)
2、java规定方法不能嵌套(一个方法中不能定义另一个方法)。
3、抽取方法时需要两个明确:方法返回值类型、参数列表
4、return两个功能:把方法的返回值进行返回、结束方法。
5、如果方法有参数,需要考虑参数值的取值范围,针对取值范围的内的数据进行操作。
有参数有返回值
有参数无返回值
无参数有返回值
无参数无返回值
6、抽取方法
方法返回值类型、参数列表
重载
1、概念
在一个类中,多个方法名一致但是参数列表不一致。
(只和方法名及参数列表有关系,和修饰符、返回值类型、异常没有关系)
2、重载方法的调用
如果重载方法有精确匹配的方法做精确匹配
如果没有精确匹配的方法做相对精确匹配
如果出现多个相对精确匹配的方法不能匹配到对应的方法会报错
传参
对于基本类型而言实际传入的参数值,所以在另一个方法中改变这个参数的值不会影响原来方法的数据。
对于引用类型而言,传参传递的是地址。如果地址不发生改变,则影响原来方法中的对象;如果地址发生改变,则不影响原来的对象。
1、实参
调用方法的时候传入的数据
实际传入的值
2、形参
定义方法时()定义的变量
来接收实参
3、注意
1、如果实参的数据类型是基本数据类型,那么传递过去的就是拷贝值。
2、如果实参数据类型是引用数据类型,那么传递的就是地址值的拷贝。
3、通过接收的拷贝值如果找到对应的堆内存做操作就会影响原值。
3、通过接收的拷贝值如果没有找到对应的堆内存做任何操作都不会影响原值。
重写
两等两小一大
递归
1、执行方法过程中再次调用本方法。
2、在递归次数过多的情况下可能会出现栈溢出错误的情况。StackOverFlowError
意义
提高代码的复用性
便于团队的合作开发
使代码的结构更加清晰