专题一 Java基础
1.3 流程控制
1.31.条件判断语句的使用
第一种、判断语句1–if
if语句第一种格式: if

if语句的语法是:
if(Boolean_expression)
{
//Statements will execute if the Boolean expression is true
}
如果布尔表达式的值为true,那么代码里面的块if语句将被执行。如果不是true,在if语句(大括号后)结束后的第一套代码将被执行。
第二种、if...else语句
任何if语句后面可以跟一个可选的else语句,当布尔表达式为false,语句被执行。

if...else的语法是:
if(Boolean_expression){
//Executes when the Boolean expression is true
}else{
//Executes when the Boolean expression is false
}
第三种、if...else if...else语句
if后面可以跟一个可选的else if...else语句,在测试不同条件下单一的if语句和else if语句是非常有用的。
当使用if,else if,else语句时有几点要牢记。
- 一个if语句可以有0个或一个else语句 且它必须在else if语句的之后。
- 一个if语句可以有0个或多个else if语句且它们必须在else语句之前。
- 一旦else if语句成功, 余下else if语句或else语句都不会被测试执行。

语法:
if...else的语法是:
if(Boolean_expression 1){
//Executes when the Boolean expression 1 is true
}else if(Boolean_expression 2){
//Executes when the Boolean expression 2 is true
}else if(Boolean_expression 3){
//Executes when the Boolean expression 3 is true
}else {
//Executes when the none of the above condition is true.
}
第四种、嵌套if...else语句
它始终是合法的嵌套if else语句,这意味着可以在另一个if或else if语句中使用一个if或else if语句。
语法:
嵌套if...else的语法如下:
if(Boolean_expression 1){
//Executes when the Boolean expression 1 is true
if(Boolean_expression 2){
//Executes when the Boolean expression 2 is true
}else{
}
}else{
}
第五种、switch语句
switch语句允许一个变量来对一系列值得相等性进行测试。每个值被称为case,并且被启动的变量会为每一个case检查。
语法:
增强的for循环的语法是:
switch(expression){
case value :
//Statements
break; //optional
case value :
//Statements
break; //optional
//You can have any number of case statements.
default : //Optional
//Statements
}
以下规则适用于switch语句:
- 在switch语句中使用的变量只能是一个byte,short,int或char。
- 在一个switch语句中可以有任何数量的case语句。每个case后跟着即将被比较的值和一个冒号。
- 对于case的值必须是相同的数据类型作为开关变量,它必须是一个常量或文字。
- 当被启动了的变量与case是相等的,那case后的语句将执行,一直到break为止。
- 当达到一个break语句,switch终止,并且控制流跳转到跟着switch语句的下一行。
- 不是每一个case需要包含一个break。如果没有出现break,控制流将贯穿到后面的case直到break为止。
- switch语句可以有一个可选默认case,它必须出现在switch的结束处。在执行一项任务时没有任何case是真,那默认case可被使用。在默认case中不需要break。
注意:从Java 7开始,表达式中也支持String。
1.3.2循环控制语句
Java中有三种主要的循环结构:
- while 循环
- do…while 循环
- for 循环
在Java5中引入了一种主要用于数组的增强型for循环。
while 循环
while是最基本的循环,它的结构为:
while( 布尔表达式 ) { //循环内容 }
只要布尔表达式为 true,循环就会一直执行下去。
/*
while循环有一个标准格式,还有一个扩展格式。
标准格式:
while(条件判断){
循环体
}
扩展格式:
初始化语句:
while(条件判断){
循环体;
步进语句;
}
*/
public class Kwhile{
public static void main(String[] args){
for (int i =1; i<=10; i++) {
System.out.println("大佬,带带我"+i);
}
System.out.println("=============");
//如果对while语句不是很熟悉的话,可以使用for语句来实行翻译做做对比。
int i =1;//初始化语句:
while (i <=10) { //2.条件判断
System.out.println("大佬,带带我" +i); //3.循环体
i++;//4.步进语句;
}
}
}
do…while 循环
对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。
do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。
do {
//代码语句
}while(布尔表达式);
注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。 如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
/*
do-while循环的标准格式:
do{
循环体
} while(条件判断);
扩展格式:
初始化语句
do{
循环体
步进语句
} while(条件判断);
*/
public class DOwhile{
public static void main(String[] args) {
for (int i =1; i<10; i++){
System.out.println("好滴,我来了"+i);
}
System.out.println("---------");
//do-while与for循环对照来看看
int i = 1;//1.初始化语句
do {
System.out.println("好滴,我来了" +i);//3.循环体
i++;//4.步进语句
} while(i <=10); //2.条件判断
}
}
for循环
虽然所有循环结构都可以用 while 或者 do...while表示,但 Java 提供了另一种语句 —— for 循环,使一些循环结构变得更加简单。
for循环执行的次数是在执行前就确定的。语法格式如下:
for(初始化; 布尔表达式; 更新) { //代码语句 }
关于 for 循环有以下几点说明:
- 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
- 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量。
- 再次检测布尔表达式。循环执行上面的过程。
/*
循环结构的基本组成部分,一般可以分成四部分:
1.初始化语句:在循环开始最初执行,而且只做唯一一次。
2.条件判断:如果成立,则循环继续;如果不成立,则循环退出。
3.循环体:重复要做的事情内容,若干行语句。
4.步进语句:每次循环之后都要进行的扫尾工作,每次循环结束之后都要执行一次。
*/
public class Foryuju {
public static void main(String[] args){
for (int i =1; i<=100; i++) { //定义一个变量i
System.out.println("大佬,带我飞!" +i);
}
}
}
Java 增强 for 循环
Java5 引入了一种主要用于数组的增强型 for 循环。
Java 增强 for 循环语法格式如下:
for(声明语句 : 表达式) { //代码句子 }
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
实例
Test.java 文件代码:
public class Test {
public static void main(String args[]){
int [] numbers = {10, 20, 30, 40, 50};
for(int x : numbers ){
System.out.print( x );
System.out.print(",");
}
System.out.print("\n");
String [] names ={"James", "Larry", "Tom", "Lacy"};
for( String name : names ) {
System.out.print( name );
System.out.print(",");
}
}
}
break 关键字
break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
break 跳出最里层的循环,并且继续执行该循环下面的语句。
语法
break 的用法很简单,就是循环结构中的一条语句:
break;
实例
Test.java 文件代码:
public class Test {
public static void main(String args[]) {
int [] numbers = {10, 20, 30, 40, 50};
for(int x : numbers ) {
// x 等于 30 时跳出循环
if( x == 30 ) {
break;
}
System.out.print( x );
System.out.print("\n");
}
}
}
continue 关键字
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
语法
continue 就是循环体中一条简单的语句:
continue;
public class Test {
public static void main(String args[]) {
int [] numbers = {10, 20, 30, 40, 50};
for(int x : numbers ) {
if( x == 30 ) {
continue;
}
System.out.print( x );
System.out.print("\n");
}
}
}
1.3.3方法的基本使用
在前面几个章节中我们经常使用到 System.out.println(),那么它是什么呢?
- println() 是一个方法。
- System 是系统类。
- out 是标准输出对象。
这句话的用法是调用系统类 System 中的标准输出对象 out 中的方法 println()。
那么什么是方法呢?
Java方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合
- 方法包含于类或对象中
- 方法在程序中被创建,在其他地方被引用
方法的优点
- 1. 使程序变得更简短而清晰。
- 2. 有利于程序维护。
- 3. 可以提高程序开发的效率。
- 4. 提高了代码的重用性。
方法的命名规则
- 1.方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。
- 2.下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。一个典型的模式是:test<MethodUnderTest>_<state>,例如 testPop_emptyStack。
方法的定义
一般情况下,定义一个方法包含以下语法:
修饰符 返回值类型 方法名(参数类型 参数名){ ... 方法体 ... return 返回值; }
方法包含一个方法头和一个方法体。下面是一个方法的所有部分:
- 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型。
- 返回值类型 :方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值。在这种情况下,returnValueType 是关键字void。
- 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
- 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
- 方法体:方法体包含具体的语句,定义该方法的功能。

如:
public static int age(int birthday){...}
参数可以有多个:
static float interest(float principal, int year){...}
注意: 在一些其它语言中方法指过程和函数。一个返回非void类型返回值的方法称为函数;一个返回void类型返回值的方法叫做过程。
实例
下面的方法包含 2 个参数 num1 和 num2,它返回这两个参数的最大值。
/** 返回两个整型变量数据的较大值 */
public static int max(int num1, int num2) {
int result;
if (num1 > num2)
result = num1;
else
result = num2;
return result;
}
更简略的写法(三元运算符):
public static int max(int num1, int num2) {
return num1 > num2 ? num1 : num2;
}
方法调用
Java 支持两种调用方法的方式,根据方法是否返回值来选择。
当程序调用一个方法时,程序的控制权交给了被调用的方法。当被调用方法的返回语句执行或者到达方法体闭括号时候交还控制权给程序。
当方法返回一个值的时候,方法调用通常被当做一个值。例如:
int larger = max(30, 40);
如果方法返回值是void,方法调用一定是一条语句。例如,方法println返回void。下面的调用是个语句:
System.out.println("欢迎访问后端小王博客!");
void 关键字
本节说明如何声明和调用一个 void 方法。
下面的例子声明了一个名为 printGrade 的方法,并且调用它来打印给定的分数。
示例
public class TestVoidMethod {
public static void main(String[] args) {
printGrade(78.5);
}
public static void printGrade(double score) {
if (score >= 90.0) {
System.out.println('A');
}
else if (score >= 80.0) {
System.out.println('B');
}
else if (score >= 70.0) {
System.out.println('C');
}
else if (score >= 60.0) {
System.out.println('D');
}
else {
System.out.println('F');
}
}
}
通过值传递参数
调用一个方法时候需要提供参数,你必须按照参数列表指定的顺序提供。
例如,下面的方法连续n次打印一个消息:
public static void nPrintln(String message, int n) {
for (int i = 0; i < n; i++) {
System.out.println(message);
}
}
方法的重载
上面使用的max方法仅仅适用于int型数据。但如果你想得到两个浮点类型数据的最大值呢?
解决方法是创建另一个有相同名字但参数不同的方法,如下面代码所示:
public static double max(double num1, double num2) {
if (num1 > num2)
return num1;
else
return num2;
}
如果你调用max方法时传递的是int型参数,则 int型参数的max方法就会被调用;
如果传递的是double型参数,则double类型的max方法体会被调用,这叫做方法重载;
就是说一个类的两个方法拥有相同的名字,但是有不同的参数列表。
Java编译器根据方法签名判断哪个方法应该被调用。
方法重载可以让程序更清晰易读。执行密切相关任务的方法应该使用相同的名字。
重载的方法必须拥有不同的参数列表。你不能仅仅依据修饰符或者返回类型的不同来重载方法。
变量作用域
变量的范围是程序中该变量可以被引用的部分。
方法内定义的变量被称为局部变量。
局部变量的作用范围从声明开始,直到包含它的块结束。
局部变量必须声明才可以使用。
方法的参数范围涵盖整个方法。参数实际上是一个局部变量。
for循环的初始化部分声明的变量,其作用范围在整个循环。
但循环体内声明的变量其适用范围是从它声明到循环体结束。它包含如下所示的变量声明:

你可以在一个方法里,不同的非嵌套块中多次声明一个具有相同的名称局部变量,但你不能在嵌套块内两次声明局部变量。
命令行参数的使用
有时候你希望运行一个程序时候再传递给它消息。这要靠传递命令行参数给main()函数实现。
命令行参数是在执行程序时候紧跟在程序名字后面的信息。
实例
public class CommandLine {
public static void main(String args[]){
for(int i=0; i<args.length; i++){
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
构造方法
当一个对象被创建时候,构造方法用来初始化该对象。构造方法和它所在类的名字相同,但构造方法没有返回值。
通常会使用构造方法给一个类的实例变量赋初值,或者执行其它必要的步骤来创建一个完整的对象。
不管你是否自定义构造方法,所有的类都有构造方法,因为Java自动提供了一个默认构造方法,默认构造方法的访问修改符和类的访问修改符相同(类为 public,构造函数也为 public;类改为 protected,构造函数也改为 protected)。
一旦你定义了自己的构造方法,默认构造方法就会失效。
实例
下面是一个使用构造方法的例子:
// 一个简单的构造函数
class MyClass {
int x;
// 以下是构造函数
MyClass() {
x = 10;
}
}
public class ConsDemo {
public static void main(String args[]) {
MyClass t1 = new MyClass();
MyClass t2 = new MyClass();
System.out.println(t1.x + " " + t2.x);
}
}
可变参数
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法。
方法的可变参数的声明如下所示:
typeName... parameterName
在方法声明中,在指定参数类型后加一个省略号(...) 。
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
实例
public class VarargsDemo {
public static void main(String args[]) {
// 调用可变参数的方法
printMax(34, 3, 3, 2, 56.5);
printMax(new double[]{1, 2, 3});
}
public static void printMax( double... numbers) {
if (numbers.length == 0) {
System.out.println("No argument passed");
return;
}
double result = numbers[0];
for (int i = 1; i < numbers.length; i++){
if (numbers[i] > result) {
result = numbers[i];
}
}
System.out.println("The max value is " + result);
}
}
finalize() 方法
Java 允许定义这样的方法,它在对象被垃圾收集器析构(回收)之前调用,这个方法叫做 finalize( ),它用来清除回收对象。
例如,你可以使用 finalize() 来确保一个对象打开的文件被关闭了。
在 finalize() 方法里,你必须指定在对象销毁时候要执行的操作。
finalize() 一般格式是:
protected void finalize() { // 在这里终结代码 }
关键字 protected 是一个限定符,它确保 finalize() 方法不会被该类以外的代码调用。
当然,Java 的内存回收可以由 JVM 来自动完成。如果你手动使用,则可以使用上面的方法。
实例
public class FinalizationDemo {
public static void main(String[] args) {
Cake c1 = new Cake(1);
Cake c2 = new Cake(2);
Cake c3 = new Cake(3);
c2 = c3 = null;
System.gc(); //调用Java垃圾收集器
}
}
class Cake extends Object {
private int id;
public Cake(int id) {
this.id = id;
System.out.println("Cake Object " + id + "is created");
}
protected void finalize() throws java.lang.Throwable {
super.finalize();
System.out.println("Cake Object " + id + "is disposed");
}
}
1.3.4 Random类的使用
Random类 (java.util)
Random类中实现的随机算法是伪随机,也就是有规则的随机。在进行随机时,随机算法的起源数字称为种子数(seed),在种子数的基础上进行一定的变换,从而产生需要的随机数字。
相同种子数的Random对象,相同次数生成的随机数字是完全相同的。也就是说,两个种子数相同的Random对象,第一次生成的随机数字完全相同,第二次生成的随机数字也完全相同。这点在生成多个随机数字时需要特别注意。
下面介绍一下Random类的使用,以及如何生成指定区间的随机数组以及实现程序中要求的几率。
1、Random对象的生成
Random类包含两个构造方法,下面依次进行介绍:
a、public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
b、public Random(long seed)
该构造方法可以通过制定一个种子数进行创建。
示例代码:
Random r = new Random();
Random r1 = new Random(10);
再次强调:种子数只是随机算法的起源数字,和生成的随机数字的区间无关。
2、Random类中的常用方法
Random类中的方法比较简单,每个方法的功能也很容易理解。需要说明的是,Random类中各方法生成的随机数字都是均匀分布的,也就是说区间内部的数字生成的几率是均等的。下面对这些方法做一下基本的介绍:
a、public boolean nextBoolean()
该方法的作用是生成一个随机的boolean值,生成true和false的值几率相等,也就是都是50%的几率。
b、public double nextDouble()
该方法的作用是生成一个随机的double值,数值介于[0,1.0)之间。
c、public int nextInt()
该方法的作用是生成一个随机的int值,该值介于int的区间,也就是-231到231-1之间。
如果需要生成指定区间的int值,则需要进行一定的数学变换,具体可以参看下面的使用示例中的代码。
d、public int nextInt(int n)
该方法的作用是生成一个随机的int值,该值介于[0,n)的区间,也就是0到n之间的随机int值,包含0而不包含n。
如果想生成指定区间的int值,也需要进行一定的数学变换,具体可以参看下面的使用示例中的代码。
e、public void setSeed(long seed)
该方法的作用是重新设置Random对象中的种子数。设置完种子数以后的Random对象和相同种子数使用new关键字创建出的Random对象相同。
3、Random类使用示例
使用Random类,一般是生成指定区间的随机数字,下面就一一介绍如何生成对应区间的随机数字。以下生成随机数的代码均使用以下Random对象r进行生成:
Random r = new Random();
a、生成[0,1.0)区间的小数
double d1 = r.nextDouble();
直接使用nextDouble方法获得。
b、生成[0,5.0)区间的小数
double d2 = r.nextDouble() * 5;
因为nextDouble方法生成的数字区间是[0,1.0),将该区间扩大5倍即是要求的区间。
同理,生成[0,d)区间的随机小数,d为任意正的小数,则只需要将nextDouble方法的返回值乘以d即可。
c、生成[1,2.5)区间的小数
double d3 = r.nextDouble() * 1.5 + 1;
生成[1,2.5)区间的随机小数,则只需要首先生成[0,1.5)区间的随机数字,然后将生成的随机数区间加1即可。
同理,生成任意非从0开始的小数区间[d1,d2)范围的随机数字(其中d1不等于0),则只需要首先生成[0,d2-d1)区间的随机数字,然后将生成的随机数字区间加上d1即可。
d、生成任意整数
int n1 = r.nextInt();
直接使用nextInt方法即可。
e、生成[0,10)区间的整数
int n2 = r.nextInt(10);
n2 = Math.abs(r.nextInt() % 10);
以上两行代码均可生成[0,10)区间的整数。
第一种实现使用Random类中的nextInt(int n)方法直接实现。
第二种实现中,首先调用nextInt()方法生成一个任意的int数字,该数字和10取余以后生成的数字区间为(-10,10),然后再对该区间求绝对值,则得到的区间就是[0,10)了。
同理,生成任意[0,n)区间的随机整数,都可以使用如下代码:
int n2 = r.nextInt(n);
n2 = Math.abs(r.nextInt() % n);
f、生成[0,10]区间的整数
int n3 = r.nextInt(11);
n3 = Math.abs(r.nextInt() % 11);
相对于整数区间,[0,10]区间和[0,11)区间等价,所以即生成[0,11)区间的整数。
g、生成[-3,15)区间的整数
int n4 = r.nextInt(18) - 3;
n4 = Math.abs(r.nextInt() % 18) - 3;
生成非从0开始区间的随机整数,可以参看上面非从0开始的小数区间实现原理的说明。
h、几率实现
按照一定的几率实现程序逻辑也是随机处理可以解决的一个问题。下面以一个简单的示例演示如何使用随机数字实现几率的逻辑。
在前面的方法介绍中,nextInt(int n)方法中生成的数字是均匀的,也就是说该区间内部的每个数字生成的几率是相同的。那么如果生成一个[0,100)区间的随机整数,则每个数字生成的几率应该是相同的,而且由于该区间中总计有100个整数,所以每个数字的几率都是1%。按照这个理论,可以实现程序中的几率问题。
示例:随机生成一个整数,该整数以55%的几率生成1,以40%的几率生成2,以5%的几率生成3。实现的代码如下:
int n5 = r.nextInt(100);
int m; //结果数字
if(n5 < 55){ //55个数字的区间,55%的几率
m = 1;
}else if(n5 < 95){//[55,95),40个数字的区间,40%的几率
m = 2;
}else{
m = 3;
}
因为每个数字的几率都是1%,则任意55个数字的区间的几率就是55%,为了代码方便书写,这里使用[0,55)区间的所有整数,后续的原理一样。
当然,这里的代码可以简化,因为几率都是5%的倍数,所以只要以5%为基础来控制几率即可,下面是简化的代码实现:
int n6 = r.nextInt(20);
int m1;
if(n6 < 11){
m1 = 1;
}else if(n6 < 19){
m1= 2;
}else{
m1 = 3;
}
在程序内部,几率的逻辑就可以按照上面的说明进行实现。
4、其它问题
a、相同种子数Random对象问题
前面介绍过,相同种子数的Random对象,相同次数生成的随机数字是完全相同的,下面是测试的代码:
Random r1 = new Random(10);
Random r2 = new Random(10);
for(int i = 0;i < 2;i++){
System.out.println(r1.nextInt());
System.out.println(r2.nextInt());
}
在该代码中,对象r1和r2使用的种子数都是10,则这两个对象相同次数生成的随机数是完全相同的。
如果想避免出现随机数字相同的情况,则需要注意,无论项目中需要生成多少个随机数字,都只使用一个Random对象即可。
b、关于Math类中的random方法
其实在Math类中也有一个random方法,该random方法的工作是生成一个[0,1.0)区间的随机小数。
通过阅读Math类的源代码可以发现,Math类中的random方法就是直接调用Random类中的nextDouble方法实现的。
只是random方法的调用比较简单,所以很多程序员都习惯使用Math类的random方法来生成随机数字。
我要一步一步往上爬
在最高点乘着叶片往前飞
任风吹干流过的泪和汗
我要一步一步往上爬
等待阳光静静看着它的脸
小小的天有大大的梦想
我有属于我的天
任风吹干流过的泪和汗
总有一天我有属于我的天

1138

被折叠的 条评论
为什么被折叠?



