第4章 Java笔记 流程控制与数组

本文介绍了Java中的流程控制结构,包括if条件语句、switch语句、while和do-while循环,以及break、continue和return的用法。此外,详细讲解了Java数组的特性,如数组的定义、初始化、静态与动态初始化的区别,以及foreach循环的使用。最后,讨论了数组在内存中的存储和如何释放数组占用的内存。
摘要由CSDN通过智能技术生成

一、分支结构

1、if条件语句

第一种形式:

if(logic expression)
	{
		statement...
	}
第二种形式:

if(logic expression)
	{
		statement...
	}
	else
	{
		statement...
	}
第三种形式:
if(logic expression)
	{
		statement...
	}
	else if(logic expression)
	{
		statement...
	}
	...//可以有零个或者多个else if语句
	else//最后一个else可以省去
	{
		statements...
	}
注意:在if语句中表面上看else后面没有任何条件,或者else if后面只有一个条件,但这不是真相:因为else本身就是一个条件!else的含义是“否则”,其隐含条件是对前面条件取反。而不是仅仅是表象中非此即彼的感觉。

在使用if...else语句时应遵循一条基本原则:总是优先把包含范围小的条件放在前面处理。如age>60和age>20两个条件,明显age>60的范围更小,所以应该先处理age>60的情况。

2、switch语句

switch (expression)
{
	case condition1:
	{
		statement(s)
		break;
	}
	case condition2:
	{
		statement(s)
		break;
	}
	...
	case conditionN:
	{
		statement(s)
		break;
	}
	default:
	{
		statement(s)
	}

}
default的含义是expression表达式的值不能与前面任何一个case标签后面的值相等。
switch语句的执行流程是:先求出expression表达式的值,然后拿这个表达式的值和case标签后面的值进行比较,一旦遇到相等的值,程序就开始执行这个case标签后面的代码,不在判断与后面case、default标签的条件是否匹配,除非遇到break;才会结束。所以每个case标签后面的break;都是非常有意义的,如果中间哪个case中没有break,程序会一直执行下去(不判断后续的case、default)直到遇到break;
二、循环结构

1、while循环语句

[init_statement]//初始化语句
while(test_expression)
{
	statement;
	[iteration_statment]//迭代语句
}

while循环每次执行循环体之前,先对test_expression循环条件求值,如果循环条件为true,则运行循环体部分。

2、do while循环语句

[init_statement]//初始化语句
do
{
	statement;
	[iteration_statment]//迭代语句
}while(test_expression);
do while循环语句与while的区别在于do while先执行循环体,然后才判断循环条件,如果循环条件为真,则执行下一次循环,否则终止循环。do while循环的循环条件后必须有一个分号,这个分号表明循环结束。值得注意的是do while 循环的循环体至少执行一次,即使判断条件为假。
3、for循环

for([init_statement];[test_statement];[iteration_statement])
{
	statement
}
for循环圆括号里面只有两个分号是必需的,初始化语句、循环条件、迭代语句部分都是可以省略的,如果省略了循环条件,则这个循环默认为true,将会产生一个死循环。
注意:for循环和while、do while循环不一样:由于while、do while循环的迭代语句紧跟着循环体,因此如果循环体不能完全执行,如使用continue语句来结束本次循环,则循环迭代语句不会被执行。但for循环的循环迭代语句并没有和循环体放在一起,因此不管是否使用continue语句来结束本次循环,循环迭代语句一样会获得执行。

三、控制循环结构

1、使用break结束循环

break用于完全结束一个循环,跳出一个循环体。不管是哪种循环,一旦在循环体中遇到break,系统将完全结束该循环,开始执行循环之后的代码。

其实break不仅可以结束其所在的循环,还可以直接结束其外层循环。此时需要在break后面紧跟着一个标签,这个标签用于标识一个外层循环。

Java中的标签就是一个紧跟着一个英文冒号的标识符。java中的标签只有放在循环语句之前才有作用。

public class BreakTest2 
{
	public static void main(String[] args) 
	{
		//外层循环,outer作为标识符
		outer:
		for(int i=0;i<5;i++){
			//内层循环
			for(int j=0;j<3;j++){
				System.out.println("i的值为: "+i+" j的值为:"+j);
				if(j==1){
					//跳出outer标签所标识的循环体
					break outer;
					//break;
				}
			}
		}
		
	}
}
2、使用continue忽略本次循环剩下语句

continue和break的区别在于,continue只是忽略本次循环剩下语句,并不会终止循环;而break则是完全终止循环的本身。continue后面也可以紧跟一个标签,用于直接跳过标签所标识循环的当次循环的剩下语句,重新开始下一次循环。

public class ContinueTest2 
{
	public static void main(String[] args) 
	{
		//外层循环,outer作为标识符
		outer:
		for(int i=0;i<5;i++){
			//内层循环
			for(int j=0;j<3;j++){
				System.out.println("i的值为: "+i+" j的值为:"+j);
				if(j==1){
					//忽略outer标签所指定的循环中本次循环所剩下语句
					continue outer;
				}
			}
		}
		
	}
}
3、使用return结束方法

return关键字的功能是结束一个方法,并不是专门用于结束循环。当一个方法执行到break语句时(return关键字后还可以跟变量、常量和表达式),这个方法将被结束。

与continue和break不同的是return直接结束整个方法,不管这个return处于多少循环之内。
四、数组类型

Java的数组要求所有的数组元素具有相同的数据类型。

数组本身是一种引用类型。一旦数组初始化完成,数组在内存中所占的空间将被固定下来,因此数组的长度是不可变的。即使把某个数组元素的数据清空,但它所占的空间依然被保留,依然属于该数组,数组的长度依然不变。

1、定义数组

type[] arrayName;
type arayName[];
对于这两种语法格式而言,通常推荐使用第一种格式。

数组是一种引用类型的变量,因此使用它定义一个变量时,仅仅是表示定义了一个引用变量,这个引用变量还没有指向任何有效的内存,因此定义数组时不能指定数组的长度。
2、数组的初始化

数组的初始化有两种方式:

静态初始化:初始化由程序员显示指定每个数组元素的初始值,由系统决定数组的长度。

动态初始化:初始化时程序员只指定数组长度,由系统为数组元素分配初始值。

2.1 静态初始化

语法格式:

arrayName=new type[]{element1,element2,element3...}

执行静态初始化时,显示指定的数组元素值的类型必须与new关键字后的type类型相同,或者是其子类的实例。

// 定义一个int数组类型的变量,变量名为intArr.
int[] intArr;
// 使用静态初始化,初始化数组时只指定数组元素的初始值,不指定数组长度。
intArr = new int[]{5, 6, 8 , 20};
// 定义一个Object数组类型的变量,变量名为objArr.
Object[] objArr ;
// 使用静态初始化,初始化数组时数组元素的类型是
// 定义数组时所指定的数组元素类型的子类
objArr = new String[]{"Java" , "李刚"};
Object[] objArr2 ;
// 使用静态初始化
objArr2 = new Object[] {"Java" , "李刚"};
除此之外,静态初始化还有下面格式:

type[] arrayName={element1,element2,element3...}

2.2 动态初始化

语法格式如下:

arrayName=new type[length]
语法格式中的type必须与定义数组时使用的type类型相同,或者是定义数组时使用的type类型的子类。

//数组的定义和初始化同时完成,使用动态初始化语法
int[] prices = new int[5];
// 数组的定义和初始化同时完成,初始化数组时元素的类型是定义数组时元素类型的子类
Object[] books = new String[4];
执行动态初始化时,程序员指定数组长度,由系统为这些数组元素分配初始值:

数组元素的类型如果是整数类型(byte、short、int和long),则数组元素的值为0;如果是浮点类型(float、double),数组元素的值为0.0;如果是字符类型(char),数组元素的值为‘\u0000’;如果是布尔类型(boolean),则数组元素的值为false;如果是引用类型(类、接口、数组),则数组元素的值为null。

注意:不要同时使用静态初始化和动态初始化,也就是说,不要在进行数组初始化时,既指定数组的长度,也为每个数组元素分配初始值。

3、foreach循环
使用foreach循环遍历数组和集合元素时,无需获得数组和集合的长度,无需根据索引来访问数组元素和集合元素,foreach循环自动遍历数组和集合中的每个元素。语法格式如下:

for(type variableName : arry|collection)
{
	//variableName自动迭代访问每个元素...
}
上面语法中type是数组元素或集合元素的类型,variableName是一个形参名,foreach循环将自动将数组元素、集合元素依次赋给该变量。

public class ForEachErrorTest
{
	public static void main(String[] args)
	{
		String[] books = {"轻量级Java EE企业应用实战" ,
		"疯狂Java讲义",
		"疯狂Android讲义"};
		// 使用foreach循环来遍历数组元素,其中book将会自动迭代每个数组元素
		for (String book : books)
		{
			book = "疯狂Ajax讲义";
			System.out.println(book);
		}
		System.out.println(books[0]);
	}
}
使用foreach循环迭代数组时,并不能改变数组元素的值,因此不要对foreach的循环变量进行赋值。
五、深入数组

1、内存中的数组

引用变量是访问真是对象的根本方式。也就是说,如果希望在程序中访问数组对象本身,则只能通过这个数组的引用变量来访问它。实际上数组对象存在堆内存中;如果引用该数组对象的数组引用变量是一个局部变量,则它被存储在栈内存中。数组在内存中的存储如下图:


所有在方法中定义的局部变量都放在栈内存中;在程序中创建一个对象时,这个对象被保存到堆内存中。只有当一个对象没有任何引用变量引用它时,系统的垃圾回收器才会在合适的时候回收它。

因此,为了让垃圾回收机制回收一个数组所占用的内存空间,可以将该数组变量赋值为null,也就切断了数组引用变量和实际数组之间的引用关系,实际的数组也就成了垃圾。

2、基本类型数组的初始化

基本类型数组初始化时,先为该数组分配内存空间,然后直接将数组元素的值存入对应数组元素中。

public class PrimitiveArrayTest
{
	public static void main(String[] args)
	{
		// 定义一个int[]类型的数组变量
		int[] iArr;
		// 动态初始化数组,数组长度为5
		iArr = new int[5];
		// 采用循环方式为每个数组元素赋值。
		for (int i = 0; i <iArr.length ; i++ )
		{
			iArr[i] = i + 10;
		}
	}
}
上面代码流程用内存存储表示为:



3、引用类型数组的初始化
引用类型数组每个数组元素里存储的是引用,它指向另一块内存,这块内存里存储了有效数据。
class Person
{
	public int age; // 年龄
	public double height; // 身高
	// 定义一个info方法
	public void info()
	{
		System.out.println("我的年龄是:" + age
			+ ",我的身高是:" + height);
	}
}
public class ReferenceArrayTest
{
	public static void main(String[] args)
	{
		// 定义一个students数组变量,其类型是Person[]
		Person[] students;
		// 执行动态初始化
		students = new Person[2];
		// 创建一个Person实例,并将这个Person实例赋给zhang变量
		Person zhang = new Person();
		// 为zhang所引用的Person对象的age、height赋值
		zhang.age = 15;
		zhang.height = 158;
		// 创建一个Person实例,并将这个Person实例赋给lee变量
		Person lee = new Person();
		// 为lee所引用的Person对象的age、height赋值
		lee.age = 16;
		lee.height = 161;
		// 将zhang变量的值赋给第一个数组元素
		students[0] = zhang;
		// 将lee变量的值赋给第二个数组元素
		students[1] = lee;
		// 下面两行代码的结果完全一样,因为lee
		// 和students[1]指向的是同一个Person实例。
		lee.info();
		students[1].info();
	}
}
上述代码执行过程的示意图如下:




4、Java多维数组的理解
定义二维数组的语法:
type[][] arrName;
因为在java中数组类型是引用类型,也就是说type[]是一种引用类型。上述的语法中的实质还是一维数组,只是其数组元素也是引用,数组元素里保存的引用指向一维数组(type[]是引用类型,第二个[]存入引用元素)。
可以采用如下语法进行二维数组的初始化:
arrName=new type[length][]
初始化多维数组时可以只指定最左边维的大小,也可以一次指定每一维的大小,如:
//同时初始化二维数组的两个维度
int[][] b=new int[3][4]; 










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值