java程序设计_80后程序员,带你深入理解Java基本的程序设计结构,不来你别后悔...

前言

现在,假定已经成功地安装了JDK,并且能够运行第2章中给出的示例程序。从现在开始将介绍Java应用程序设计。本章主要讲述程序设计相关的基本概念(如数据类型、分支以及循环)在Java中的实现方式。

非常遗憾,需要告诫大家,使用Java编写GUI应用程序并不是一件很容易的事情,它需要编程者掌握很多相关的知识才能够创建窗口、添加文本框和按钮等。而基于GUI的Java应用程序设计技术与本章将要介绍的程序设计基本概念相差甚远,因此在本章中给出的所有例子都是旨在说明一些相关概念而设计的“玩具式”程序,它们仅仅通过shell窗口输入输出。

最后需要说明,对于一个具有使用C++经验的程序员来说,这一章的内容只需要浏览一下,应该重点阅读分布在正文中的C/C++注释。而对于具有使用Visual Basic等其他编程背景的程序员来说,可能会发现其中的绝大多数概念都很熟悉,只是在语法上有比较大的差异,因此,需要非常仔细地阅读本章的内容。

一个简单的Java应用程序

下面看一个最简单的Java应用程序,它只发送一条消息到控制台窗口中:

420cc8a350cee4e2568e53b4e5a4c871.png

这个程序虽然很简单,但因为所有的Java应用程序都具有这种结构,所以值得花一些时间对它进行研究。首先,Java对大小写敏感。如果出现了大小写拼写错误(例如,将main拼写成了Main),程序就无法运行。

下面逐行地查看一下这段源代码。关键字public被称为访问修饰符(access modifier),它用于控制程序的其他部分对这段代码的访问级别。在第5章中将会更加详细地介绍访问修饰符的具体内容。关键字class表明Java程序中的全部内容都包含在类中。这里,只需要将类作为一个加载程序逻辑的容器,程序逻辑定义了应用程序的行为,在下一章中将会用大量的篇幅介绍Java类。

正如第1章所述,类是构建所有Java应用程序和applet的构建块。Java应用程序中的全部内容都必须放置在类中。

关键字class后面紧跟类名。Java中定义类名的规则很宽松。名字必须以字母开头,后面可以跟字母和数字的任意组合。长度基本上没有限制。但是不能使用Java保留字(比如public或class)作为类名。(保留字列表请参阅附录A。)

从类名FirstSample可以看出,标准的命名规范为:类名是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该为大写。(这种在一个单词间使用大写字母的方式被称为“camel case”,以它自己为例,应该写成“CamelCase”。)

源代码的文件名必须与公有类的名字相同,并用.java作为扩展名。因此,存储这段源代码的文件名必须为FirstSample.java。(再次提醒大家注意,大小写是非常重要的,千万不能写成firstsample.java。)

如果已经正确地命名了这个文件,并且源代码中没有任何录入错误,那么在编译这段源代码之后,就会得到一个包含该类字节码的文件。Java编译器将字节码文件自动地命名为FirstSample.class,并与源文件存储在同一个目录下。最后,使用下面这行命令运行这个程序:

java FirstSample

(请记住,不要添加.class扩展名。)程序执行之后,控制台上将会显示“We will not use

‘Hello,World’!”。

当使用

java ClassName

运行编译程序时,Java虚拟机将从指定类中的main方法开始执行,因此为了代码能够得到执行,在类的源文件中必须包含一个main方法。当然,也可以把用户自定义的方法添加到类中,并且在main方法中调用它们。(下一章,将讲述如何自己定义方法。)

其解决方案放到网上让所有人监督检查,这是一种非常了不起的举动。“bug 展示”对程序员来说是一种十分有用的资源,甚至程序员可以对感兴趣的bug进行“投票”。得票多的bug在下一个将发行的版本的JDK中得到解决的可能性就大。

需要注意源代码中的括号{ }。在Java中,像在C/C++中一样,用花括号划分程序的各个部分(通常称为块)。Java中任何方法的代码都用“{”开始,用“}”结束。

花括号的使用风格曾经引发过许多无谓的争论。我们的习惯是把匹配的花括号上下对齐。

不过,由于空白符会被Java编译器忽略,所以自然可以选用任何自己喜欢的风格。在下面讲述各种循环语句时,我们还会详细地介绍花括号的使用。

我们暂且不去理睬关键字static void,而仅把它们当作编译Java应用程序必需的一部分就行了。

学习完第4章,这些内容的作用就会被揭晓。现在需要记住:每个Java应用程序都必须有一个main方法,其格式如下所示:

f3fcfccda85631255eacb05252b29641.png

接下来,让我们研究一下这段代码:

{System.out.println("We will not use 'Hello, World!'");}

一对花括号表示方法体的开始与结束,在这个方法中只包含一条语句。与大多数程序设计语言一样,可以将Java语句看成是这种语言的句子。在Java中,每个句子必须用分号结束。特别要说明一点,回车不是语句的结束标志,因此,如果需要可以将一条语句写在多行上。

在上面这个main方法体中只包含了一条语句,其功能是:将一个文本行输出到控制台上。

在这里,使用了System.out对象并调用了它的println方法。注意,点号用来调用一个方法。

Java使用的通用语法是

object.method( parameters)

这等价于函数调用。

在这个例子中,调用了println方法并传递给它一个字符串参数。这个方法将传递给它的字符串参数显示在控制台上。然后,终止这个输出行,以便每次调用println都会在新的一行上显示输出。需要注意一点,Java与C/C++一样,都采用双引号分隔字符串。本章稍后将会详细地讲解有关字符串的知识。

与其他程序设计语言一样,在Java的方法中,可以没有参数,也可以有零个、一个或多个参数。(有的程序员把参数叫做变元。)对于一个方法,即使没有参数也需要书写圆括号。例如,不带参数的println方法只打印一个空行。使用下面的语句:

System.out.println( );

注释

与大多数程序设计语言一样,Java中的注释也不会出现在可执行程序中。因此,可以在源程序中添加任意多的注释,而不必担心可执行代码会膨胀。在Java中,有三种表示注释的方式。最常用的方式是使用 //,其注释内容从 // 开始到本行结尾。

System.out.println("We will not use 'Hello, World!'"); //is this too cute?

当需要比较长的注释时,可以在每行的注释前面标记 //,也可以使用 /* 和 */ 将一段比较长的注释括起来。请参看例3-1。

例3-1 FirstSample.java

41f7e6dd0e4372b36227a6e6749207cf.png
ea5076592eeb0f6b068b53c6eb6e4be1.png

第三种注释可以用来自动地生成文档。这种注释以 /**开始,以 */ 结束。有关这种注释的详细内容和自动生成文档的具体方法请参阅第4章。

数据类型

Java是一种强类型语言(strongly typed language)。这就意味着必须为每一个变量声明一种类型。在Java中,一共有8种基本类型(primitive type),其中有4个整型、2个浮点类型、1个用于表示Unicode编码的字符单元的字符类型char(请参见论述char类型的章节)和1个用于表示真值的boolean类型。

整型

整型用于表示没有小数部分的数值,它允许是负数。Java提供了4种整型,具体内容如表3-1所示。

bb7497c93132bf699eb4b60aa2d1270d.png

在通常情况下,int类型非常有用,但要表示星球上的居住人数,就要使用long类型了。byte和short类型主要用于特定的场合,例如,底层的文件处理或者需要控制占用存储空间量的大数组。

在Java中,整型的范围与运行Java代码的机器无关。这就解决了软件从一个平台移植到另一个平台,或者在同一个平台中的不同操作系统之间进行移植给程序员带来的诸多问题。与此相反,C和C++程序需要针对不同的处理器选择最为有效的整型,这样就有可能造成一个在32位处理器上运行很好的C程序在16位系统上运行却发生整数溢出。由于Java程序必须保证在所有机器上都能够得到相同的运行结果,所以每一种数据类型的取值范围必须固定。

长整型数值有一个后缀L(如4000000000L)。十六进制数值有一个前缀0x(如0xCAFE)。八进制有一个前缀0,例如,010对应八进制中的8。很显然,八进制表示法比较容易混淆,所以建议最好不要使用八进制常数。

浮点型

浮点类型用于表示有小数部分的数值。在Java中有两种浮点类型,具体内容如表3-2所示。

ffacfb817b2834bdd26a727aa88f5edf.png

double表示这种类型的数值精度是float类型的两倍。(有人称之为双精度。)绝大部分应用程序都采用double类型。在很多情况下,float类型的精度很难满足需求。例如,用7位有效数字足以精确表示普通雇员的年薪,但表示公司总裁的年薪可能就不够用了。实际上,只有很少的情况适合使用float类型,例如,需要快速地处理单精度数据,或者需要存储大量数据。

float类型的数值有一个后缀F(例如,3.402F)。没有后缀F的浮点数值(如3.402)默认为double类型。当然,也可以在浮点数值后面添加后缀D(例如,3.402D)。

在JDK 5.0中,可以使用十六进制表示浮点数值。例如,0.125可以表示成0x1.0p-3。在十六进制表示法中,使用p表示指数,而不是e。

所有的浮点数值计算都遵循IEEE 754规范。下面是三个特殊的浮点数值:

• 正无穷大

• 负无穷大

• NaN

上面这三个数值用于表示溢出和出错情况。例如,一个正整数除以0的结果为正无穷大。计算0/0或者负数的平方根结果为NaN。

char类型

要想弄清char类型,就必须了解Unicode编码表。Unicode打破了传统字符编码方法的限制。在Unicode出现之前,已经有许多种不同的标准:美国的ASCII、西欧语言中的ISO 8859-1、俄国的KOI-8、中国的GB118030和BIG-5等等。这样就产生了下面两个问题:一个是对于任意给定的代码值,在不同的编码方案下有可能对应不同的字母;二是采用大字符集的语言其编码长度有可能不同。例如,有些常用的字符采用单字节编码,而另一些字符则需要两个或更多个字节。

设计Unicode编码就是要解决这些问题。在20世纪80年代开始启动设计工作时,人们认为两个字节的代码宽度足以能够将世界上各种语言的所有字符进行编码,并有足够的空间留给未来的扩展。在1991年发布了Unicode 1.0,当时仅占用65 536个代码值的一小部分。在设计Java时决定采用16位的Unicode字符集,这样会比使用8位字符集的程序设计语言有很大的改进。

十分遗憾,经过一段时间,不可避免的事情发生了。Unicode字符超过了65 536个,其主要原因是添加了大量的汉语、日语和韩国语言中的表意文字。现在,16位的char类型已经不能满足描述所有Unicode字符的需要了。

下面利用一些专用术语解释一下Java语言解决这个问题的基本方法。从JDK 5.0开始。代码点(code point)是指与一个编码表中的某个字符对应的代码值。在Unicode标准中,代码点采用十六进制书写,并加上前缀U+,例如U+0041就是字母A的代码点。Unicode的代码点可以分成17个代码级别(code plane)。第一个代码级别称为基本的多语言级别(basic multilingual plane),代码点从U+0000到U+FFFF,其中包括了经典的Unicode代码;其余的16个附加级别,代码点从U+10000到U+10FFFF,其中包括了一些辅助字符(supplementary character)。

UTF-16编码采用不同长度的编码表示所有Unicode代码点。在基本的多语言级别中,每个字符用16位表示,通常被称为代码单元(code unit);而辅助字符采用一对连续的代码单元进行编码。这样构成的编码值一定落入基本的多语言级别中空闲的2048字节内,通常被称为替代区域(surrogate area)(U+D800到U+DBFF用于第一个代码单元,U+DC00到U+DFFF用于第二个代码单元)。这种设计十分巧妙,我们可以从中迅速地知道一个代码单元是一个字符的编码,还是一个辅助字符的第一或第二部分。例如,对于整数集合的数学符号 ,它的代码点是U+1D56B,并且是用两个代码单元U+D835和U+DD6B编码的。(有关编码算法的描述请参阅http://en.wikipedia.org/wiki/UTF-16。)

在Java中,char类型用UTF-16编码描述一个代码单元。

我们强烈建议不要在程序中使用char类型,除非确实需要对UTF-16代码单元进行操作。最好将需要处理的字符串用抽象数据类型表示。(有关这方面的内容将在稍后讨论。)

前面已经说过,在有些情况下,可能需要用到char的值。最常见的情况是字符常量。例如,'A'是一个编码为65的字符常量,它与"A"完全不同,是一个包含字符A的字符串。Unicode代码单元可以表示为十六进制的值,其范围从 到。例如,™是注册符号(™);π是希腊字母π。

除了可以采用转义序列符u表示Unicode代码单元的编码之外,还有一些用于表示特殊字符的转义序列符,请参看表3-3。所有这些转义序列符都可以出现在字符常量或字符串的引号内。

例如,'™'或"Hello"。转义序列符u还可以出现在字符常量或字符串的引号之外(而其他所有转义序列不可以)。例如:

public static void main (String[] args)

这种形式完全符合语法规则,[和 ] 是 [ 和 ] 的Unicode代码点的UTF-16编码。

186269f82659d8f8424bcbf96585cc8e.png

boolean类型

boolean(布尔)类型有两个值:false和true,用来判定逻辑条件。这两个值不能与整型进行相互转换。

变量

在Java中,每一个变量属于一种类型(type)。在声明变量时,变量所属的类型位于前面,随后是变量名。这里列举一些声明变量的例子:

double salary;

int vacationDays;

long earthPopulation;

boolean done;

注意,用于Java中,声明是一条完整的语句,因此每一个声明都必须以分号结束。

变量名必须是一个以字母开头的字母或数字序列。需要注意,与大多数程序设计语言相比,Java中“字母”和“数字”的范围要大。字母包括'A'~'Z'、'a'~'z'、'_'和在某种语言中代表字母的任何Unicode字符。例如,德国的用户可以在变量名中使用字母'ä';希腊人可以使用π。同样,数字包括'0'~'9'和在某种语言中代表数字的任何Unicode字符。但'+'和'©'这样的符号不能出现在变量名中,空格也不行。变量名中所有的字符都是有意义的,并且大小写敏感。对变量名的长度没有限制。

另外,不能将变量名命名为Java保留字。(请参看附录A中的Java保留字列表。)

可以在一行中声明多个变量:

int i, j; //both are integers

不过,不提倡使用这种风格。逐一声明每一个变量可以提高程序的可读性。

初始化变量

声明一个变量之后,必须利用赋值语句对变量进行显式初始化,千万不要使用一个未被初始化的变量。例如,Java编译器认为下面语句序列是错误的:

int vacationDays;

System.out.println(vacationDays); //ERROR-variable not initialized

要想对一个已经声明过的变量进行赋值,就需要将变量名放在等号(=)左侧,具有相应取值的Java表达式放在等号的右侧。

int vacationDays;

vacationDays = 12;

也可以将变量的声明和初始化放在同一行中。例如:

int vacationDays = 12;

最后,在Java中可以将声明放在代码中的任何地方。例如,在Java中,下列代码的书写形式是完全合法的:

double salary = 65000.0;

System.out.println(salary);

int vacationDays = 12; // ok to declare a variable here

在Java中,变量的声明尽可能地靠近变量第一次使用的地方,这是一种良好的程序编写风格。

extern int i;

是声明一个变量。在Java中,不区分变量的声明与定义。

常量

在Java中,利用关键字final声明常量。例如:

39e249fc7ef3851f2acae7b8314491ac.png

关键字final表示这个变量只能被赋值一次。一旦被赋值之后,就不能够再更改了。习惯上,常量名使用大写。

在Java中,经常希望某个常量可以在一个类中的多个方法中使用,通常将这些常量称为类常量。可以使用关键字static final设置一个类常量。下面是使用类常量的例子:

7f9004f38f2972af17be1685f1458e46.png

需要注意,类常量的定义位于main方法的外部。因此,在同一个类的其他方法中也可以使用这个常量。而且,如果一个常量被声明为public,那么其他类的方法也可以使用这个常量。在这个例子中,Constants2.CM_PER-INCH就是这样一个常量。

运算符

在Java中,使用算术运算符+、-、*、/ 表示加、减、乘、除运算。当参与 / 运算的两个操作数都是整数时,表示整数除法;否则,表示浮点除法。整数的求余操作(有时称为取模)用%表示。例如,15/2等于7,15%2等于1,15.0/2等于7.5。

需要注意,整数被0除将会产生一个异常,而浮点数被0除将会得到无穷大或NaN。

可以在赋值语句中采用简化的格式书写二元算术运算符。

例如,

x += 4;

等价于

x = x + 4;

(通常,将运算符放在赋值号的左侧,如*= 或 %=。)

自增运算符与自减运算符

当然,程序员都知道加1、减1是数值变量最常见的操作。在Java中,借鉴了C和C++的实现方式,也使用了自增、自减运算符:n++将变量n的当前值加1;n--将n的值减1。例如:

int n =12;

n++;

n的值将变为13。因为这些运算符改变了变量的值,所以它的操作数不能是数值。例如,4++就是一条非法的语句。

实际上,这两个运算符有两种形式。上面介绍的是运算符放在后面的“后缀”形式,还有一种“前缀”形式(++n)都是对变量值加1。但在表达式中,这两种形式就有区别了。前缀方式先进行加1运算;后缀方式则使用变量原来的值。

int m = 7;

int n = 7;

int a = 2 * ++m;//now a is 16, m is 8

int b = 2 * n++;//now b is 14, n is 8

我们建议不要在其他表达式的内部使用++,这样编写的代码很容易令人感到迷惑,并会产生烦人的bug。

显然,++ 运算符构成了C++语言名称,这也引发了有关程序设计语言的第一个笑话。C++的反对者认为这种语言的名称也存在着bug,他们说:“因为只有对它改进之后,我们才有可能使用它,所以它的名字应该命名为++C。”

关系运算符与boolean运算符

Java具有各种关系运算符。其中,使用两个等号 = = 检测是否相等。例如,3 = = 7的值为false。

使用 != 检测是否不相等。例如,3 != 7的值为true。

另外,经常使用的运算符还有 (大于)、<=(小于等于)和>=(大于等于)。

Java沿用了C++的习惯,用&&表示逻辑“与”、用 || 表示逻辑“或”。从!= 运算符很容易看出,!表示逻辑“非”。&&和 || 是按照“短路”方式求值的。如果第一个操作数已经能够确定值,第二个操作数就不必计算了。如果用 && 对两个表达式(expression)进行计算:

expression1 && expression2

并且第一个表达式值为false,那么结果不可能为真。因此,第二个表达式就没有必要计算了。这种方式可以避免一些错误的发生。例如,表达式:

x != 0 && 1 / x > x + y // no division by 0

当x为0时,不计算第二部分,因此1 / x不被计算也不会出现除以0的错误。

与之类似,对于expression1 || expression2 ,当第一个表达式为true时,结果自动为true,不必再计算第二部分。

最后,Java支持三元操作?:,在很多时候,这个操作非常有用。表达式

condition ? expression1 : expression2

当条件为真时计算第1个表达式,否则计算第2个表达式。

例如:

x < y ? x : y

返回x和y中较小的那个值。

位运算符

在处理整型数值时,可以直接对组成整型数值的各个位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位。位运算符包括:

&(“与”)、|(“或”)、^(“异或”)、~(“非”)

这些运算符在位模式下工作。例如,如果n是一个整型变量,并且用二进制表示的n从右数第4位为1,那么

int fourthBitFromRight = (n & 8) / 8;

返回1;否则返回0。通过使用2的幂次方和&运算可以将其他位屏蔽掉,而只保留其中的某一位。

数学函数与常量

在Math类中,包含了各种各样的数学函数。在编写不同类别的程序时,可能需要的函数也不同。

要想计算一个数值的平方根,可以使用sqrt方法:

double x = 4;double y = Math.sqrt(x);System.out.println(y); //prints 2.0

在Java中,没有幂运算。因此求幂需要借助于Math类的pow方法。语句:

double y = Math.pow(x, a) ;

将y的值设置为x的a次方(xa)。pow方法有两个double类型的参数,其返回结果也为double类型。

Math类提供了一些常用的三角函数:

Math.sin

Math.cos

Math.tan

Math.atan

Math.atan2

还有指数函数以及它的反函数—自然对数:

Math.exp

Math.log

最后,Java还提供了两个用于表示π和e常量的近似值:

Math.PI

Math.E

数值类型之间的转换

在程序运行时,经常需要将一种数值类型转换为另一种数值类型。图3-1给出了数值类型之间的合法转换。

ce92592dc29becee8111dadd35a848cb.png

图3-1 数值类型之间的合法转换

在图3-1中有6个实箭头,表示无数据丢失的转换;有3个虚箭头,表示可能有精度损失的转换。例如,123 456 789是一个大整数,它所包含的位数比float类型所能够表达的位数多。当将这个整型数值转换为float类型时,将会得到同样大小的结果,但却失去了一定的精度。

int n = 123456789;

float f = n; // f is 1.23456792E8

当使用上面两个数值进行二元操作时(例如n + f,n是整数,f是浮点数),先要将两个操作数转换为同一种类型,然后再进行计算。

• 如果两个操作数中有一个是double类型的,那么另一个操作数将会转换为double类型。

• 否则,如果其中一个操作数是float类型,那么另一个操作数将会转换为float类型。

• 否则,如果其中一个操作数是long类型,那么另一个操作数将会转换为long类型。

• 否则,两个操作数都将被转换为int类型。

强制类型转换

在上一小节中看到,在必要的时候,int类型的值将会自动地转换为double类型。但另一方面,有时也需要将double转换成int。在Java中,允许进行这种数值之间的类型转换,当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换(cast)实现这个操作。

强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,随后紧跟待转换的变量名。

例如:

double x = 9.997;

int nx = (int)x;

这样,变量nx的值为9。强制类型转换将通过截断小数部分来把一个浮点值转换为整型。

如果想对浮点数进行舍入运算,得到最接近的整数(在很多情况下,希望使用这种操作方式),就需要使用Math.round方法:

double x = 9.997;

int nx = (int) Math.round (x);

现在,变量nx的值为10。当调用round的时候,仍然需要使用强制类型转换(int)。其原因是round方法返回的结果为long类型,由于存在信息丢失的可能性,所以只有使用显示的强制类型转换才能够将long类型转换成int类型。

括号与运算符级别

表3-4给出了运算符的优先级。如果不使用圆括号,就按照给出的运算符优先级次序进行计算。同一个级别的运算符按照从左到右的次序进行计算(除了表中给出的右结合运算符之外。)

例如,由于 && 的优先级比 || 的优先级高,所以表达式

a && b || c

等价于

( a && b ) || c

又因为 += 是右结合运算符,所以表达式

a += b += c

等价于

a += ( b += c )

也就是将b += c 的结果(加上c之后的b)加到a上。

583aa43c197a693cbcfc16a614316e13.png

枚举类型

有些时候,变量的取值仅在一个有限的集合内。例如:销售的服装或比萨饼只有小、中、大和超大这四种尺寸。当然,可以将这些尺寸编码为1、2、3、4或S、M、L、X。但这样做存在着一定的隐患。在变量中很可能保存的是一个错误的值(如0或m)。

从JDK 5.0开始,针对这种情况,可以自定义枚举类型。枚举类型包括有限个命名的值。例如,enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE };

现在,可以声明这样一种类型的变量:

Size s = Size.MEDIUM;

Size类型的变量只能存储该类型声明中给定的某个枚举值,或者null值。

有关枚举类型的详细内容将在第5章介绍。

字符串

从概念上讲,Java字符串就是Unicode字符序列。例如,串“Java™”由5个Unicode字符J、a、v、a和™组成。Java 没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类的一个实例:

String e = ""; //an empty string

String greeting = "Hello";

3.6.1 代码点与代码单元

Java字符串由char值序列组成。从前面已经看到,char数据类型是一个采用UTF-16编码表示Unicode代码点的代码单元。大多数的常用Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

length方法将返回采用UTF-16编码表示的给定字符串所需要的代码单元数量。例如:

String greeting = "Hello";

int n = greeting.length( ); // is 5.

要想得到实际的长度,即代码点数量,可以调用:

int cpCount = greeting.codePointCount(0,greeting.length( ));

调用s.charAt(n) 将返回位置n的代码单元,n介于0 ~ s.length( )-1之间。例如:

char first = greeting.charAt(0); //first is 'H'

char last = greeting.charAt(4); //last is 'o'

要想得到第i个代码点,应该使用下列语句

int index = greeting.offsetByCodePoints(0,i);

int cp = greeting.codePointAt(index);

为什么我们对代码单元大惊小怪?请考虑下列语句:

is the set of integers

使用UTF-16编码表示 需要两个代码单元。调用

char ch = sentence.charAt(1)

返回的不是空格,而是 的第二个代码单元。为了避免这种情况的发生,请不要使用char类型。这太低级了。

如果想要遍历一个字符串,并且依次查看每一个代码点,可以使用下列语句:

int cp = sentence.codePointAt(i);

if (Character.isSupplementaryCodePoint(cp)) i += 2;

else i++;

非常幸运,codePointAt方法能够辨别一个代码单元是辅助字符的第一部分还是第二部分,并能够返回正确的结果。也就是说,可以使用下列语句实现回退操作:

i--;

int cp = sentence.codePointAt(i);

if (Character.isSupplementaryCodePoint(cp)) i--;

子串

String类的substring方法可以从一个较大的字符串提取出一个子串。例如:

String greeting = "Hello";

String s = greeting.substring(0, 3);

创建了一个由字符“Hel”组成的字符串。

substring的第二个参数是不希望复制的第一个代码单元。这里复制的代码单元位置为0、1、2(从0到2,包括0和2)。在substring中的计数是从0~3。

substring的工作方式有一个优点:容易计算子串中代码单元的数量。字符串s.substring(a, b) 将包含b-a个代码单元。例如,子串“Hel”的代码单元数量为3-0=3。

字符串编辑

String类没有提供用于修改现存字符串的方法。如果希望将greeting的内容修改为“Help!”,不能直接地将greeting的最后两个位置的字符修改为'p'和'!'。这对于一个C 程序员来说会感到无从下手。如何修改这个字符串呢?在Java中实现这项操作相当容易,首先提取需要的子串,然后再拼接上需要替换的字符串。

greeting = greeting.substring(0,3) + "p!";

上面这条语句将greeting当前值修改为“Help!”。

由于不能修改Java字符串中的字符,所以在Java文档中将String类对象称为不可变字符串,如同数字3永远是数字3一样,字符串“Hello”永远包含H、e、l、l和o的代码单元序列,而不能修改其中的任何一个字符。当然,可以修改字符串变量greeting的内容,让它引用一个不同的字符串,如同可以将一个存放3的数值变量改成存放4一样。

这样做是否会降低运行效率呢?看起来好象修改一个代码单元要比创建一个新字符串更加简洁。答案是:也对,也不对。的确,通过拼接“Hel”和“p!”来创建一个新字符串的效率确实不高。但是,不可变字符串却有一个优点:编译器可以将字符串共享。

要想了解具体的工作方式,可以想象将各种字符串存放在公共的存储池中。字符串变量指向存储池中相应的位置。如果复制一个字符串变量,那么原始字符串与复制的字符串共享相同的字符。总而言之,Java的设计者认为共享带来的高效率远远胜过于提取子串,然后再拼接字符串所带来的低效率。

查看一下程序会发现:不会经常修改字符串,而是对字符串进行比较。当然,在有些情况下,直接对字符串进行操作会更加有效。(例如,将源自文件或键盘的单个字符汇集成字符串。)

为此Java提供了一个独立的StringBuilder类,在第12章中将详细地阐述它。如果不太注重字符串的处理效率,就可以不理会StringBuilder,而只使用String。

拼接

与绝大多数的程序设计语言一样,Java语言允许使用 + 号连接(拼接)两个字符串。

String expletive = "Expletive";

String PG13 = "deleted";

String message = expletive + PG13;

上面的代码将“Expletivedeleted”赋给变量message。(注意,单词之间没有空格,+号按照给定的次序将两个字符串拼接起来。)

当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串。(在第5章中可以看到,任何一个Java对象都可以转换成字符串。)例如:

int age = 13;

String rating = "PG" + age;

rating得到“PG13”。

这种特性通常用在输出语句中。例如,

System.out.println ("The answer is" + answer);

这是一条合法的语句,并且将会打印出所希望的结果(单词is后面加了一个空格,输出时也会加上这个空格。)

检测字符串是否相等

可以使用equals方法检测两个字符串是否相等。如果字符串s与字符串t相等,则表达式s.equals(t)返回true;否则,返回false。需要注意,s与t可以是字符串变量,也可以是字符串常量。

例如,表达式

"Hello".equals(greeting)

是合法的。要想检测两个字符串是否相等,而不区分大小写,可以使用equalsIgnoreCase方法。

"Hello".equalsIgnoreCase("hello")

一定不能使用 = = 运算符检测两个字符串是否相等!这个运算符只能够确定两个字符串是否被放置在同一个位置。当然,如果字符串放置在同一个位置,它们必然相等。但是,完全有可能将内容相同的两个字符串放置在不同的位置上。

String greeting = "Hello"; //initialize greeting to a string

if (greeting = = "Hello") ...

// probably true

if (greeting.substring(0, 3) = = "Hel")...

//probably false

如果虚拟机总是将相同的字符串共享,就可以使用 == 运算符检测是否相等。但实际上只有字符串常量是共享的,而+或substring等操作产生的结果都不是共享的。因此,永远不要使用 ==运算符测试字符串的相等性,否则在程序中会出现很糟糕的bug,从表面上看很像随机产生的间歇性错误。

Java中的String类包含了50多个方法。令人惊讶的是绝大多数都很有用,可以想象使用的机会有多么频繁。下面的API注释汇总了最常用的部分方法。

java.lang.string 1.0

• char charAt (int index)

返回指定位置的代码单元。除非对底层的代码单元感兴趣,否则不需要调用这个方法。

• int codePointAt(int index) 5.0

返回从给定位置开始或结束的代码点。

• int offsetByCodePoints(int startIndex, int cpCount) 5.0

返回从startIndex代码点开始,位移cpCount后的代码点索引。

• int compareTo(String other)

按照字典顺序,如果字符串位于other之前,则返回一个负数;如果字符串位于other之后,则返回一个正数;如果两个字符串相等,则返回0。

• boolean endsWith(String suffix)

如果字符串以suffix结尾,则返回true。

• boolean equals(Object other)

如果字符串与other相等,则返回true。

• boolean equalsIgnoreCase(String other)

如果字符串与other相等(忽略大小写),则返回true。

• int index0f(String str)

• int index0f(String str, int fromIndex)

• int index0f(int cp)

• int index0f(int cp, int fromIndex)

返回与字符串str或代码点cp匹配的的第一个子串的开始位置,该位置从索引0或fromIndex开始计算。如果在原始串中不存在str,则返回-1。

• int lastIndex0f(String str)

• int lastIndex0f(String str, int fromIndex)

• int lastindex0f(int cp)

• int lastindex0f(int cp, int fromIndex)

返回与字符串str或代码点cp匹配的最后一个子串的开始位置,该位置从原始串尾端或

fromIndex开始计算。

• int length( )

返回字符串的长度。

• int codePointCount(int startIndex, int endIndex) 5.0

返回startIndex和endIndex-1之间的代码点数量。没有配成对的替代字符作为代码点计数。

• String replace(CharSequence oldString,CharSequence newString)

返回一个新字符串,该字符串用newString代替原始字符串中所有的oldString。可以用String或

StringBuilder对象作为CharSequence参数。

• boolean startsWith(String prefix)

如果字符串以preffix字符串开始,则返回true。

• String substring(int beginIndex)

• String substring(int beginIndex, int endIndex)

返回一个新字符串,该串包含从原始字符串beginIndex到串尾或endIndex-1的所有代码单元。

• String toLowerCase( )

返回一个新字符串,该串将原始字符串中的所有大写字母改成了小写字母。

• String toUpperCase( )

返回一个新字符串,该串将原始字符串中的所有小写字母改成了大写字母。

• String trim( )

返回一个新字符串,该串删除了原始字符串头部和尾部的空格。

阅读联机API文档

正如前面所看到的,String类包含许多方法。而且,在标准库中有几千个类,方法数量则更加惊人。要想记住所有的类和方法是一件不太不可能的事情。因此,了解在线API文档十分重要,从中可以查阅到标准类库中的所有类和方法。API文档是JDK的一部分,它是HTML格式的。让浏览器指向安装JDK的docs/api/index.html子目录,就可以看到如图3-2所示的屏幕。

可以看到,屏幕被分成三个窗框。在左上方的小窗框中显示了可使用的所有包。在它下面稍大的窗框中列出了所有的类。点击任何一个类名之后,该类的API文档就会显示在右侧的大窗框中(请参看图3-3)。例如,要获得有关String类方法的更多信息,可以滚动第二个窗框,直到看见String链接为止,然后点击这个链接。

然后,滚动右面的窗框,直到看见按字母顺序排列的所有方法为止(请参看图3-4)。点击任何一个方法名便可以查看这个方法的详细描述(参见图3-5)。例如,如果点击compare-ToIgnoreCase链接,就会看到compareToIgnoreCase方法的描述。

6923d8b17d9f612833f7d9d7ab414026.png
c5a51f21baa6287febc348012531b96c.png
d491dd03bad96a6c9df15b9aed531661.png
3f7d6dcba5a2c971f90c5f6c10674c29.png

输入输出

为了增加后面例子程序的趣味性,需要程序能够接收输入,并以适当的格式输出。当然,现代的程序都使用GUI收集用户的输入,编写这种界面的程序需要使用较多的工具与技术,目前还不具备这些条件。主要原因是需要熟悉Java程序设计语言,因此只要有简单的用于输入输出的控制台就可以了。第7章~第9章将详细地介绍GUI程序设计。

读取输入

前面已经看到,打印输出到“标准输出流”(即控制台窗口)是一件非常容易的事情,只要调用System.out.println即可。而在JDK 5.0之前却没有从控制台窗口读取输入的简便方法。值得庆贺的是,这一状况终于得到了改变。

要想通过控制台进行输入,首先需要构造一个Scanner对象,它附属于“标准输入流”System.in。

Scanner in = new Scanner(System.in);

现在,就可以使用Scanner类的各种方法实现输入操作了。例如,nextLine方法将输入一行。

System.out.print("What is your name?");

String name = in.nextLine( );

在这里,使用nextLine方法的主要原因是在输入行中可能包含空格。如果读取的是一个单词(以空白符作为分隔符),则可以调用

String firstName = in.next( );

要想读取一个整数,可以使用nextInt方法。

System.out.print("How old are you?");

int age = in.nextInt( );

与此类似,要想读取下一个浮点数,可以使用nextDouble方法。

在例3-2的程序中,询问用户姓名和年龄,然后打印一条如下格式的消息:

Hello, Cay. Next year, you’ll be 46

最后,在程序的最开始添加上一行:

import java.util.* ;

Scanner类定义在java.util包中。当使用的类不是定义在基本java.lang包中时,一定要使用import指示字将相应的包加载进来。有关包与import指示字的详细描述请参看第4章。

例3-2 InputTest.java

2b715df1479831b39836e8229bd2e7cf.png
71dc3ff8a164398ca78c4a62fe6aabf4.png

String input = JOptionPane.showInputDialog(promptString)它的返回值是用户输入的字符串。

例如,可以这样询问用户的名字:

String name = JOptionPane.showInputDialog("What is your name?");

如果想要输入数值,还需要附加一步操作。

JOptionPane.showInputDialog方法返回一个字符串,而不是一个数值。不过可以使用Integer.parseInt或Double.parseDouble方法将字符串转换成数值。例如,String input = JOptionPane.showInputDialog("How old are you?");

int age = Integer.parseInt(input);

如果用户键入了45,字符串变量input将得到字符串“45”,然后调用Integer.parseInt方法将这个字符转换为数值45。

JOptionPane类定义在javax.swing包中,因此,需要添加语句:

import javax.swing.*;

最后,需要说明一点,当程序调用JOptionPane.showInputDialog时,需要通过调用System.exit(0)结束应用程序。这主要是技术上的原因。当显示一个对话框时,就启动了一个新的控制线程。在main方法退出后,新线程并没有自动地终止。要想终止所有的线程,需要调用System.exit方法。(关于线程的详细论述请参见本书卷II第1章。)下面这段程序应用于JDK 5.0之前的版本,它的功能与例3-2一样。

96e0d50ffc734e478cf4b988a291fb60.png

java.util.Scanner 5.0

• Scanner (InputStream in)

用指定的输入流创建一个Scanner对象。

• String nextLine( )

读取输入的下一行内容。

• String next( )

读取输入的下一个单词(以空格作为分隔符)。

• int nextInt( )

• double nextDouble( )

读取并转换下一个表示整数或浮点数的字符序列。

• boolean hasNext( )

检测输入中是否还有单词。

• boolean hasNextInt( )

• boolean hasNextDouble( )

检测是否还有表示整数或浮点数的下一个字符序列。

javax.swing.JOptionPane 1.2

• static String showInputDialog(Object message)

显示一个对话框,带有信息提示、一个输入框和“OK”、“Cancel”按钮。这个方法将返回用户输入的字符串。

java.lang.System 1.0

• static void exit(int status)

终止虚拟机并将状态码传递给操作系统。习惯上,非0的状态码表示出错。

格式化输出

可以使用System.out.print(x) 将数值x输出到控制台上。这条命令将以x对应的数据类型所允许的最大非0数字位数打印输出x。例如:

double x = 10000.0 / 3.0;

System.out.print(x);

打印

3333.3333333333335

如果希望显示美元、美分等符号,有可能会出现问题。

在JDK 5.0之前,格式化数值曾引起过一些争议。现在,JDK 5.0沿用了C语言库函数中的printf方法。例如,调用

System.out.printf("%8.2f", x);

可以用8个字符的宽度和小数点后两位的精度打印x。也就是说,打印输出一个空格和7个字符,如下所示:

3333.33

在printf中,可以使用多个参数,例如:

System.out.printf("Hello, %s. Next year, you’ll be %d", name, age);

每一个以%字符开始的格式说明符都用相应的参数替换。格式说明符结尾的转换符将指示被格式化的数值类型:f表示浮点数,s表示串,d表示十进制整数。表3-5给出了所有转换符。

dbae19970c1aaaae0336b31a0cd6c813.png

另外,还可以给出控制格式化输出的各种标志。表3-6给出了所有的标志。例如,逗号标志添加了分组的分隔符。即

System.out.printf("%, .2f", 10000.0 / 3.0);

打印

3,333.33

可以使用多个标志,例如,“%, ( .2f”,使用分组的分隔符并将负数括在括号内。

061c740be2ec66e7678310169df5a9d0.png

可以使用静态的String.format方法创建一个格式化的字符串,而不打印输出:

String message = String.format("Hello, %s. Next year, you’ll be %d", name, age);

尽管在第4章之前,并没有对Date类型进行详细描述,但基于完整性的考虑,这里简略地讨论一下printf方法的日期与时间的格式化选项。可以使用两个字符的格式,以t开始,以表3-7中任意字母结束。例如,

System.out.printf("%tc", new Date( ));

这条语句将用下面的格式打印当前的日期和时间:

Mon Feb 09 18:05:19 PST 2004

689aba9eaabd11e7dc820f4158e0646b.png
fb5ac9aa6da6dcfc8497c3cb7a82dc01.png

从表3-7可以看到,某些格式只给出了给定日期的一部分信息。例如,只有日期或只有月份。

如果需要多次对日期操作才能实现对每一部分格式化的目的就太笨拙了。为此,可以采用一个格式化的字符串指出要被格式化的参数索引。索引必须紧跟在%后面,并以$终止。例如,System.out.printf("%1$s %2$tB %2$te, %2$tY", "Due date:", new Date( ));

打印

Due date: February 9, 2004

作为替代方案,还可以使用 < 标志。它指出前面格式说明中的参数要再次使用。也就是说,下列语句将产生与前面语句同样的输出结果。

System.out.printf("%s %tB %

现在,已经了解了printf方法的所有特性。图3-7给出了格式说明符的语法图。

ab846e2ee0e69702747dd376714c6b9d.png

控制流程

与任何程序设计语言一样,Java使用条件语句和循环来确定控制流程。在本节中,先讨论条件语句,然后再讨论循环语句,最后再介绍显得有些笨重的switch语句。当需要对某个表达式的多个值进行检测时,可以使用switch语句。

块作用域

在深入学习控制结构之前,需要了解块(block)的概念。

块(即复合语句)是指由一对花括号括起来的若干条简单的Java语句。块确定了变量的作用域。一个块可以嵌套在另一个块中。下面就是在main方法块中嵌套另一个语句块的例子。

b501f01ed7815cee25092ed3546cbf75.png

但是,不能在嵌套的两个块中声明同名的变量。例如,下面的代码就有错误,而无法通过编译:

25af573def95b284abad90a8fe24a356.png

条件语句

在Java中,条件语句的格式为

if (condition) statement

这里的条件必须用括号括起来。

与绝大多数程序设计语言一样,Java常常希望在某个条件为真时执行多条语句。在这种情况下,使用块语句(block statement),格式为

{statement1statement2. . .}

例如:

if (yourSales >= target){performance = "Satisfactory";bonus = 100;}

当yourSales大于或等于target时,将执行括号中的所有语句(请参看图3-8)。在Java中,比较常见的条件语句格式如下所示(请参看图3-9):

if (condition) statement1 else statement2

0aa0f179508e26b71d0057eeea56dfdc.png

例如:

33b4a9d21eeb939911551bbb74b32c49.png
2a3fa52de7889a3008282e69e0794f0e.png

其中else部分是可选的。else与最邻近的if构成一组,因此,在语句

00db5dc8f7a9d8d230cded91dae970ee.png

中else与第2个if配对。

重复地交替出现if…else if…是很常见的一种情况(请参看图3-10)。例如:

03b8b36ac78a6314565e11323f0fd562.png
95eded9dfde6f06e932279fe11c4be4e.png

循环

while循环当条件为true时执行一条语句(也可以是一个语句块)。常用的格式为while (condition) statement如果开始循环条件就为false,则循环体一次也不执行请参看图3-11)。

546e75fc6fa8a718a569cb5ef1b5b9d0.png

例3-3的程序将用来计算需要多长时间能够存储特定数量的退休金。假定每年存入相同数量的金额,而且利率是固定的。

在这个例子中,增加了一个计数器,并在循环体中更新当前的累积数量,直到总值超过目标值为止。

51ee73ef6a2e175f0cab6911dcf5d346.png

(千万不要使用这个程序安排退休计划。这里忽略了通货膨胀和所期望的生活水准。)

while循环语句首先检测循环条件。因此,循环体中的代码有可能不被执行。如果希望循环体至少执行一次,就应该将检测条件放置在最后。使用do/while循环语句可以实现这种操作方式。

它的语法格式为:

do statement while (condition);

这种循环语句先执行语句(通常是一个语句块),再检测循环条件;然后重复语句,再检测循环条件,以此类推。在例3-4的代码中,首先计算退休账户中的余额,然后再询问是否打算退休:

b4f43ab15041ab58d535b6169eba0b7a.png

只要用户回答 “N”,循环就重复执行(请参看图3-12)。这是一个需要至少执行一次的循环的很好例子,因为用户必须先看到余额才能知道是否满足退休所用。

例3-3 Retirement.java

fbc51a7de5fd4a1d9a540eaed491aefd.png
266070e4e6d9c3371167b7c56f016f55.png

例3-4 Retirement2.java

7c447b75ccb9e8b73eba64853e226a95.png

确定循环

for循环语句是支持迭代的一种通用结构,使用每次迭代之后更新的计数器或类似的变量来控制迭代次数。如图3-13所示,下面的程序将数字1~10输出到屏幕上。

for (int i = 1; i <= 10; i++)

System.out.println(i);

for语句的第1部分通常用于对计数器初始化;第2部分给出每次循环前要检测的循环条件;

第3部分指示如何更新计数器。

与C++一样,尽管Java允许在for循环的各个部分放置任何表达式,但有一条不成文的规则:

for语句的3个部分应该对同一个计数器变量进行初始化、检测和更新。若不遵守这一规则,编写的循环常常晦涩难懂。

aed880ff2a5749edd3db8b7f25117c26.png

即使遵守了这条规则,也还有可能出现很多问题。例如,下面这个倒计数的循环:

for (int i = 10; i > 0; i--)

System.out.println("Counting down . . . " + i);

System.out.println("Blastoff!");

当在for语句的第1部分中声明了一个变量之后,这个变量的作用域就为for循环的整个循环体。

cd549f50c1a0d0d9c2c2f77576b789e4.png
d394f0ec36b919455bbc0d3db1c7fef7.png

尤其是,如果在for语句内部定义一个变量,那么这个变量值不能在循环体外使用。因此,如果希望在for循环体之外使用循环计数器的最终值,就要确保这个变量在循环语句的前面且在外部声明

fc7111e0c8169e5b3967520bbfd7f2fa.png

另一方面,可以在独立的不同for循环中定义同名的变量:

a3067c38226d4912afe3df05cdf7916d.png

for循环语句只不过是while循环的一种便捷形式。例如

6fe816a418112a7684f1486916f4e2f5.png

可以重写为:

b23c0c6a85bfcd8cfb15149f6efbef7e.png

例3-5给出了一个应用for循环的典型例子。

这个程序用来计算抽奖中奖的概率。例如,如果必须从1~50之间的数字中取6个数字来抽奖,那么会有 (50×49×48×47×46×45)/(1×2×3×4×5×6) 种可能的结果,所以中奖的几率是1/15 890 700。祝你好运!

一般情况下,如果从n个数字中抽取k个数字,那么会有下列公式得到的结果。

41609388f751cff9495287b455de4cbf.png

下面的for循环语句计算了上面这个公式的值:

0227b626cab96ce61354e41c138005e6.png

例3-5 LotteryOdds.java

9bd65060045f9b6ce7ff3ceef35403d0.png

多重选择—switch语句

在处理多个选项时,使用if/else结构显得有些笨拙。Java有一个与C/C++完全一样的switch语句。

例如,如果建立一个如图3-14所示的包含4个选项的菜单系统,就应该使用下列代码:

16f177f62c1403348116c7d200d94f5c.png
d184219b9b1baa289459b9805df7c6c6.png
a419ace368140114c884f58357422bcf.png
78624661d6fe2c751085c883a8eb5ba4.png

switch语句将从匹配值的case标签开始执行直到遇到break语句,或者执行到switch语句的结束处为止。如果没有匹配的case标签,而有default子句的话,就执行这个子句。

注意,case标签必须是整数或枚举常量,不能检测字符串。

例如,下面这段代码就存在错误。

0021d4227273770cf6f880febf40a546.png

中断控制流程语句

尽管Java的设计者将goto作为保留字,但实际上并没有打算在语言中使用它。通常,人们认为使用goto是一种拙劣的程序设计风格。当然,也有一些程序员认为反对goto的呼声似乎有些过分(例如,Donald Knuth就曾编著过一篇名为“Structured Programming with goto statements”的著名文章)。该文章说:无限制地使用goto语句确实是导致错误的根源,但在有些情况下,偶尔使用goto跳出循环还是有益处的。Java设计者同意这种看法,甚至在Java语言中增加了一条带标签的break,以此来支持这种程序设计风格。

下面先来看看不带标签的break语句。与用于退出switch语句的break语句一样,它也可以用于退出循环。例如:

0a3f37a0284c23ca2ca65b8ca61f2c92.png

当循环开始时years>100,或者在循环中间balance≥goal时退出循环语句。当然,也可以在不使用break的情况下计算years的值,如下所示:

1f30f9cfc9fa8102712db829226d3db4.png

但是需要注意,在这个版本中,检测了两次balance < goal。为了避免重复检测,有些程序员更加偏爱break语句。

与C++不同,Java还提供了一种带标签的break语句,用于跳出多重嵌套的循环语句。有些时候,在嵌套很深的循环语句中会发生一些不可预料的事情。此时可能更加希望完全跳出嵌套的所有循环语句。通过添加一些额外的条件判断来实现对各层循环的检测是很不方便的。

这里有一个例子说明了break语句的工作状态。请注意,标签必须放置在最外层的循环之前,并且必须紧跟一个冒号。

7a48f27bbe1867d7a20438434e828409.png

如果输入有误,则通过执行带标签的break跳转到带标签的语句块末尾。对于任何使用break的语句,都需要检测循环是正常结束,还是通过break跳出。

661a33da4f09a3a0e24a0e785fccc337.png

因此,如果希望使用一条goto语句,并将一个标签放置在想要跳过的语句块前面,就可以使用break语句!当然,我们并不提倡使用这种方式。另外需要注意,只能跳出语句块,而不能跳入语句块。

最后,还有一个continue语句。与break语句一样,它将中断正常的控制流程。continue语句将控制转移到最内层循环的首部。例如:

3598b5828b06c2c31977311b58d5b6c8.png

如果n<0,则continue语句立刻跳到循环首部,越过了当前迭代的其余部分。如果将continue语句用于for循环中,就可以跳到for循环的“更新”部分。例如,以下这个循环:

84baa488b31b0949226612fa75046687.png

如果n<0,则continue语句跳到count++语句。还有一种带标签的continue语句,将跳到与标签匹配的循环首部。

觉得文章不错的话,可以转发此文关注小编,之后持续更新干货文章!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值