栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java程序设计与数据结构答案(java程序的三种基本控制结构)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java程序设计与数据结构答案(java程序的三种基本控制结构)

Java 初探,本章先来了解一下 Java 里的基础知识。

一、一个简单的 Java 程序

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

public class FirstSample {
	public static viod main(String[] args) {
		System.out.println("Hello world!");
	}
}

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

我们来分析一下这段源代码。首先,关键字 public 称为访问修饰符,这些修饰符用于控制程序的其他部分对这段代码的访问级别。关键字 class 表明 Java 类。类是构建所有 Java应用程序和 applet 的构建块,因此 Java 应用程序中的全部内容都必须放置在类中。

关键字 class 后面紧跟类名。Java 中定义类名的规则很宽松。名字必须以字母开头,后面可以跟字符和数字的任意组合。长度基本上没有限制。但是不能使用 Java 保留字(例如public 或 class)作为类名。标准的命名规范为(FirstSample 就遵循了这个规范):类名是以大写字母开头的名词。如果名字由多个单词组成,每个单词的第一个字母都应该大写(称为骆驼命名法)。

源代码的文件名必须与公共类的名字相同,并用 .java作为扩展名。因此,存储这段源代码的文件名必须是 FirstSample.java。

如果文件名和源代码都没有错误,对文件编译之后,就会得到一个包含这个类字节码的文件 FirstSample.class,并存储在同一个目录下。我们来执行一下这段代码,输入命令:java FirstSample ,控制台上将显示 “Hello world!”。

运行已编译的程序时,Java虚拟机总是从指定类中的 main 方法的代码开始执行,因此为了代码能够执行,在类的源文件中必须包含一个 main 方法。

二、注释

Java中的注释不会出现在可执行程序中。因此,我们可以在源代码中根据需要添加任意多的注释,而不必担心可执行代码会膨胀。在Java中,一共有 3 种表示注释的方式。最常用的方式是 //,其注释内容从 // 开始到本行结尾。

// this is a line of text
System.out.println("Hello world!");

当需要更长的注释时,既可以用 //,也可以使用 结束。

public class FirstSample {
	public static viod main(String[] args) {
		System.out.println("Hello world!");
	}
}
三、数据类型

Java 中一共有 8 种数据类型,其中有 4 种整型、2 种浮点类型、1 种字符串类型 char和 1 种用于表示真值的 boolean 类型。

1、整型

整形用于表示没有小数部分的数值,允许是负数。Java中提供了 4 中整型:

类型存储需求取值范围
int4 字节-2 147 483 648 ~ 2 147 483 647(刚刚超过 20 亿)
short2 字节-32 768 ~ 32 767
long8 字节-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807
byte1 字节-128 ~ 127

在通常情况下,int 类型最常用。但如果想要表示整个地球的居住人口。就需要使用 long 类型了。byte 和 short 类型主要用于特定的应用场合,例如,底层的文件处理或者储存空间很宝贵时的大数组。

在 Java 中,所有的数值类型所占据的字节数与平台无关。

2、浮点类型

浮点类型用于表示有小数部分的数值。在Java中有两种浮点类型:

类型存储需求取值范围
float4 字节大约 ±3.402 823 47E+38F(有效位数为 6 ~ 7 位)
double8 字节大约 ±1.797 693 134 862 315 70E+308(有效位数为 15 位)

double 表示这种类型的数值精度是 float 类型的两倍(有人称之为双精度数值)。在很多情况下,float 类型的精度(6 ~ 7 位有效数字)并不能满足需求。实际上,只有很少的情况下适合使用 float 类型。
float 类型的数值有一个后缀 F 或 f(例如,3.14F)。没有后缀 F 的浮点数值(如 3.14)总是默认为 double 类型。当然,也可以在浮点数值后面添加后缀 D 或 d(例如 3.14D)。

注意:浮点数值不适用于无法接受舍入误差的金融计算。例如,命令 System.out.pringln(2.0 - 1.1)将打印出 0.89999999999,而不是我们期望的 0.9.这种输入误差的主要原因是浮点数采用二进制系统表示,而在二进制系统中无法精确地表示分数 1/10。这就好像十进制无法精确的表示分数 1/3 一样。如果在数值计算中不允许有任何舍入误差,就应该使用 BigDecimal 类,本章稍后将介绍这个类。

3、char 类型

char 类型的字面量值是要用单括号括起来。例如,‘A’ 是编码值为 65 的字符常量。它与 “A” 不同,“A” 是包含一个字符 A 的字符串。char 类型的值可以表示为十六进制值,其范围从 /u0000 到 /uFFFF。例如,/u2122 表示商标符号(™),/u03C0 表示希腊字母 Π。

4、boolean 类型

boolean(布尔)类型有两个值:false 和 true,用来判断逻辑条件。整型值和布尔值之间不能相互转换。

四、变量与常量

在 Java 中,使用变量来存储值。常量就是值不变的变量。

1、声明变量

每个变量都有一个类型。在生命变量时,先指定变量的类型,然后是变量名。变量名必须是一个以字母开头并由字母或数字构成的序列。不能使用 Java 保留字作为变量名。声明变量示例:

double salary;
int vacationDays;
long earthPopulation;
boolean done;

注意:变量名对大小写敏感,例如,hireday 和 hireDay 是两个不同的变量名。一般来讲,在对两个不同的变量进行命名时,最好不要只存在大小写上的差异。

2、变量初始化

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

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

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

int vacationDays;
vacationDays = 12;

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

int vacationDays = 12;

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

3、常量

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

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

public class Constant {
	public static final CM_PRE_INCN = 2.54;
	public static void main(String[] args) {
		double paperWidth = 8.5;
		double paperHeight = 11;
		System.out.println("Paper size in centimeters: "
			+ paperWidth * CM_PRE_INCN + " by " + paperHeight * CM_PRE_INCN);
	}
}
4、枚举类型

有时候,变量的取值只在一个有限的集合内。例如,销售的服装或比萨只有小、中、大和超大这四种尺寸。
针对这种情况,可以使用自定义枚举类型。枚举类型包括有限个命名的值。例如,

enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE }

就可以声明这种类型的变量:

Size s = Size.MEDIUM;

有关枚举类型的详细内容将在后面介绍。

五、运算符

运算符用于连接值。

1、算术运算符

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

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

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 次幂(x a的次方)。pow 方法有两个 double 类型的参数,其返回类型也是 double 类型。

Math 类还提供了一些常用的三角函数、指数函数、反函数、自然对数等等。

3、数值类型之间的转换

我们经常需要将一种数值类型转换为另一种数值类型。


上图中有 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 类型。 4、强制类型转换

在必要的时候,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);
5、结合赋值和运算符

可以在赋值中使用二元运算符,这是一种很方便的简写形式。x += 4; 等价于 x = x + 4;

6、自增与自减运算符

以下代码:

int n = 12;
n++;

将 n 的值改为 13.由于这些运算符改变的是变量的值,所以它们不能应用于数值本身。例如,4++ 就不是一个合法的语句。

实际上,这些运算符有两种形式:上面介绍的是运算符放在操作数后面的 “后缀” 形式。还有一种 “前缀” 形式:++n。后缀和前缀形式都会是变量值加 1 或减 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。

7、关系和 boolean 运算符

Java 包含丰富的关系运算符。要检测相等性,可以使用两个符号 ==。另外可以使用 !=。最后还有经常使用的 <、>、<=、>= 运算符。

使用 && 表示逻辑 “与” 运算符,使用 || 表示逻辑 “或” 运算符。从 != 运算符可以想到,感叹号 ! 就是逻辑非运算符。&& 和 || 运算符是按照 “短路” 方式来求值的:如果第一个操作数已经能够确定表达式的值,第二个操作数就不必计算了。

最后一点,Java 支持三元操作符 ? :,这个操作符有时很有用。

8、括号与运算符级别

表达式中,如果不使用圆括号,就按照给出的运算符优先级次序进行计算。同一个级别的运算符按照从左到右的次序进行计算(但右结合运算符除外)。例如,由于 && 的优先级比 || 的优先级高,所以表达式 a && b || c 等价于 (a && b) || c。又因为 += 是右结合运算符,所以表达式 a += b += c 等价于 a += (b += c),也就是将 b += c 的结果(加上 c 之后的 b)加到 a 上。

六、字符串

Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个预定义类,很自然地叫做 String。每个用双引号括起来的字符串都是 String 类的一个实例。

String e = ""; // an empty string
String greeting = "Hello";
1、字串

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

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

创建一个由字符 “Hel” 组成的字符串。
substring 方法的第二个参数是不想复制的第一个位置。这里要复制位置为 0、1 和 2(从 0 到 2,包括 0 和 2)的字符。在 substring 中从 0 开始计数,直到 3 为止,但不包含 3.

substring 的工作方法有一个优点:容易计算字串的长度。字符串 s.substring(a, b) 的长度为 b - a。例如,字串 “Hel” 的长度为 3 - 0 = 3。

2、拼接

Java 中允许使用 + 号连接(拼接)两个字符串。

String expletive = "Expletive";
String PG13 = "deleted";
String message = expletive + PG13;

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

当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串,任何一个 Java 对象都可以转换成字符串。例如:

int age = 13;
String rating = "PG" + age;

将 rating 的值设置为 “PG13”。

如果需要把多个字符串放在一起,用一个界定符分割,可以使用静态 join 方法:

String all = String.join(" / ", "S", "M", "L", "XL");
// all is the string "S / M / L / XL"
3、检测字符串是否相等

可以使用 equals 方法检测两个字符串是否相等。对于表达式:s.equals(t)
如果字符串 s 与字符串 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。

4、空串与 Null 串

空串 “” 是长度为 0 的字符串。可以调用以下代码检查一个字符串是否为空:if (str.length() == 0) 或 if (str.equals(""))。

空串是一个 Java 对象,有自己的串长度(0)和内容(空)。不过,String 变量还可以存放一个特殊的值,名为 null,表示目前没有任何对象与该变量关联。要检查一个字符串是否为 null,要使用以下条件:if (str == null)。

有时要检查一个字符串不是 null 也不是空串,这种情况下就需要使用以下条件:if (str != null && str.length() != 0)。

5、String API

Java 中的 String 类包含了 50 多个方法。令人惊讶的是它们绝大多数都很有用,可以想见使用的频率非常高。下面的 API 注释汇总了一部分最常用的方法。

char charAt(int index)
返回给定位置的代码单元。除非对底层的代码单元感兴趣,否则不需要调用这个方法。int codePointAt(int index)
返回从给定位置开始的码点。int offsetByCodePoints(int startIndex, int cpCount)
返回从 startIndex 码点开始,cpCount 个码点后的码点索引。int compareTo(String other)
按照字典顺序,如果字符串位于 other 之前,返回一个负数;如果字符串位于 other 之后,返回一个正数;如果两个字符串相等,返回 0.IntStream codePoints()
将这个字符串的码点作为一个流返回。调用 toArray 将它们放在一个数组中new String(int[] codePoints, int offset, int count)
用数组中从 offset 开始的 count 个码点构造一个字符串。boolean empty()boolean blank()
如果字符串为空或者由空格组成,返回 true。boolean equals(Object other)
如果字符串与 other 相等,返回 trueboolean equalsIgnoreCase(String other)
如果字符串与 other 相等(忽略大小写),返回 true。boolean startsWith(String prefix)boolean endsWith(String suffix)
如果字符串以 prefix 开头或以 suffix 结尾,则返回 true。int indexOf(String str)int indexOf(String str, int fromIndex)int indexOf(int cp)int indexOf(int cp, int fromIndex)
返回与字符串 str 或码点 cp 匹配的第一个字串的开始位置。从索引 0 或 fromIndex 开始匹配。如果在原始字符串中不存在 str,则返回 -1。int lastIndexOf(String str)int lastIndexOf(String str, int fromIndex)int lastIndexOf(int cp)int lastIndexOf(int cp, int fromIndex)
返回与字符串 str 或码点 cp 匹配的最后一个字符串的开始位置。从原始字符串末尾或 fromIndex 开始匹配。int length()
返回字符串代码单元的个数。int codePointCount(int startIndex, int endIndex)
返回 startIndex 和 endIndex - 1 之间的码点个数。String replace(CharSequence oldString, CharSequence newString)
返回一个新字符串。这个字符串用 newString 代替原始字符串中所有的 oldString。可以用 String 或 StringBuilder 对象作为 CharSequence 参数。String substring(int beginIndex)String substring(int beginIndex, int endIndex)
返回一个新的字符串。这个字符串包含原始字符串中从 beginIndex 到字符串末尾或 endIndex - 1 的所有代码单元。String toLowerCase()String toUpperCase()
返回一个新字符串。这个字符串将原始字符串中的大写字母改为小写,或者将原始字符串中的所有小写字母改成大写字母。String trim()String strip()
返回一个新字符串。这个字符串将删除原始字符串头部或尾部小于等于 U+0020 的字符(trim)或空格(strip)。String join(CharSequence delimiter, CharSequence, CharSrquence… elements)
返回一个新字符串,用给定的定界符连接所有元素。String repeat(int count)
返回一个字符串,将当前字符串重复 count 次。

在 API 注释中,有一些 CharSequence 类型的参数。这是一种接口类型,所有字符串都属于这个接口。

6、构建字符串

有些时候,需要由较短的字符串构建字符串。例如,按键或来自文件中的单词。如果采用字符串拼接的方式来达到这个目的,效率会比较低。每次拼接字符串时,都会构建一个新的 String 对象,既耗时,又浪费空间。使用 StringBuilder 类就可以避免这个问题的发生。

如果需要用许多个小段的字符串来构建一个字符串,那么应该按照下列步骤进行。首先,构建一个空的字符串构建器:

StringBuilder builder = new StringBuilder();

当每次需要添加一部分内容时,就调用 append 方法。

builder.append(ch); // appends a single character
builder.append(str); // appends a string

在字符串构建完成时就调用 toString 方法,将可以得到一个 String 对象,其中包含了构建器中的字符序列。

String completedString = builder.toString();

注意:StringBuilder 类在 Java 5 中引入。这个类的前身是 StringBuffer,它的效率稍有些低,但允许采用多线程的方式添加或删除字符。如果所有字符串编辑操作都是在单个线程中执行(通常都是这样),则应该使用 StringBuilder。这两个类的 API 是一样的。

下面的 API 注释包含了 StringBuilder 类中的重要方法。

StringBuilder()
构建一个空的字符串构建器。int length()
返回构建器或缓冲器中的代码单元数量。StringBuilder append(String str)
追加一个字符串并返回 this。StringBuilder append(char c)
追加一个代码单元并返回 this。StringBuilder appendCodePoint(int cp)
追加一个码点,并将其转换为一个或两个代码单元并返回 this。void setCharAt(int i, char c)
将第 i 个代码单元设置为 c。StringBuilder insert(int offset, String str)
在 offset 位置插入一个字符串并返回 this。StringBuilder insert(int offset, char c)
在 offset 位置插入一个代码单元并返回 this。StringBuilder delete(int startIndex, int endIndex)
删除偏移量从 startIndex 到 endIndex-1 的代码单元并返回 this。String toString()
返回一个与构建器或缓冲器内容相同的字符串。 七、输入与输出

为了增加后面示例程序的趣味性,需要程序能够接受输入,并适当地格式化输出。当然,现代的程序都是用 GUI 手机用户的输入,然而,编写这种界面的程序需要使用较多的工具与技术,目前还不具备这些条件。我们的第一要务是熟悉 Java 程序设计语言,因此我们要使用基本的控制台来实现输入输出。

1、读取输入

前面已经看到,将输入打印到控制台窗口是一件很容易的事情,只要调用 System.out.println 即可。然而,读取 “标准输入流” System.in 就没有那么简单了。要想通过控制台进行输入,首先需要构造一个与 “标准输入流” System.in 关联的 Scanner 对象。

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 方法。

java.util.Scanner

Scanner(InputStream in)
用给定的输入流创建一个 Scanner 对象。String nextLine();
读取输入的下一行内容。String next()
读取输入的下一个单词(以空格作为分隔符)。int nextInt()double nextDouble()
读取并转换下一个表示整数或浮点数的字符序列。boolean hasNext()
检测输入中是否还有其他单词。boolean hasNextInt()boolean hasNextDouble()
检测是否还有下一个表示整数或浮点数的字符序列。 八、控制流程 1、块作用域

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

public static void main(String[] args)
{
	int n;
	...
	{
		int k;
		...
	} // k is only defined up to here
}

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

public static void main(String[] args)
{
	int n;
	...
	{
		int k;
		int n; // ERROR--can't redefine n in inner block
	}
}
2、条件语句

在 Java 中,一般的条件语句如下所示:

if (yourSales >= target)
{
	performance = "Satisfactory";
	bonus = 100 + 0.01 * (youSales - target);
}
else
{
	performance = "Unsatisfactory";
	bonus = 0;
}

其中 else 部分是可选的。else 子句与最邻近的 if 构成一组。

反复使用 if…else if… 很常见。例如:

if (yourSales >= 2 * target) 
{
	performance = "Ecellent";
	bonus = 1000;
} 
else if (yourSales >= 1.5 * target) 
{
	performance = "Fine";
	bonus = 500;
} 
else if (yourSales >= target) 
{
	performance = "Satisfactory";
	bonus = 100;
} 
else {
	System.out.println("You're fired");
}
3、循环

当条件为 true 时,while 循环执行一条语句(也可以是一个块语句)。

while (balance < gogal) {
	balance += payment;
	double interest = balance * interestRate / 100;
	balance += interest;
	years++;
}
System.out.println(years + " years.");

while 循环语句在最前面检测循环条件。因此,循环体中的代码有可能一次都不执行。如果希望循环体至少执行一次,需要使用 do/while 循环将检测放在最后。它的语法如下:

do {
	balance += payment;
	double interest = balance * interestRate / 100;
	balance += interest;
	years++;
	// print current balance
	...
	// ask if ready to retire and get input
} while (input.equals("N"));

只要用户回答 “N”,循环就重复执行。

4、确定循环

for 循环语句是支持迭代的一种通用结构,由一个计数器或类似的变量控制迭代次数,每次迭代后这个变量将会更新。下面的循环将数字 1 ~ 10 输出到屏幕上。

for (int i = 1; i <= 10; i++)
	System.out.println(i);

for 语句的第 1 部分通常是对计数器初始化;第 2 部分给出每次新一轮循环执行前要检测的循环条件;第 3 部分指定如何更新计数器。

5、多重选择:switch 语句

在处理多个选项时,使用 if/else 结构显得有些笨拙。这时候就用到 switch 语句了。例如:

Scanner in = new Scanner(System.in);
System.out.print("Select an option (1, 2, 3, 4) ");
int choice = in.nextInt();
switch (choice) {
	case 1:
		...
		break;
	case 2:
		...
		break;
	case 3:
		...
		break;
	case 4:
		...
		break;
	default:
		// bad input
		...
		break;
}

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

注意:有可能出发多个 case 分支。如果在 case 分支语句的末尾没有 break 语句,那么,就会接着执行下一个 case 分支语句。这种情况相当危险,常常会引发错误。

case 标签可以是:

类型为 byte、short、int、char的常量表达式。枚举常量从 Java 7 开始,case 标签还可以是字符串字面量。
例如:

String input = ...;
switch (input.toLowerCase()) {
	case "yes": // OK since Java 7
		...
		break;
	...
}

当在 switch 语句中使用枚举常量时,不必在每个标签中指明枚举名,可以由 switch 的表达式值推导得出。例如:

Size sz = ...;
switch (sz) {
	case SMALL; // no need to use Size.SMALL
		...
		break;
	...
}
九、大数

如果基本的整数和浮点数精度不能满足需求,那么可以使用 java.math 包中两个很有用的类,BigInteger 和 BigDecimal。这两个类可以处理包含任意长度数字序列的数值。BigInteger 类实现任意精度的整数运算,BigDecimal 实现任意精度的浮点数运算。

使用静态的 valueOf 方法可以将普通的个数值转换为大数:

BigInteger a = BigInteger.valueOf(100);

对于更大的数,可以使用一个非字符串参数的构造器:

BigInteger reallyBig = new BigInteger("22212312321334254342253156345162311");

遗憾的是,不能使用人们熟悉的算术运算符(如:+ 和 *)处理大数,则需要使用大数类中的 add 和 multiply 方法。

吧IG iNTEGERC = a.add(b); // c = a + b
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2))); // d = c * (b + 2)

java.math.BigInteger

BigInteger add(BigInteger other)BigInteger subtract(BigInteger other)BigInteger multiply(BigInteger other)BigInteger divide(BigInteger other)BigInteger mod(BigInteger other)
返回这个大整数和另一个大整数 other 的和、差、积、商以及余数。BigInteger sqrt()
得到这个 BigInteger 的平方根int cpmpareTo(BigInteger other)
如果这个大整数与另一个大整数 other 相等,返回 0;如果这个大整数小于另一个大整数 other,返回负数;否则,返回正数。static BigInteger valueOf(long x)
返回值等于 x 的大整数

java.math.BigDecimal

BigDecimal add(BigDecimal other)BigDecimal subtract(BigDecimal other)BigDecimal multiply(BigDecimal other)BigDecimal divide(BigDecimal other)BigDecimal divide(BigDecimal other, RoundingMode mode)
返回这个大实数与 other 的和、差、积、商。如果商是个无限循环小数,第一个 divide 方法会抛出一个异常。要得到一个舍入的结果,就要使用第二个方法。int compareTo(BigDecimal other)
如果这个大实数与 other 相等,返回 0;如果这个大实数小于 other,返回负数;否则,返回正数。static BigDecimal valueOf(long x)static BigDecimal valueOf(long x, int scale)
返回值等于 x 或 x / 10 scale次方 的一个大实数。 十、数组

数组存储相同类型值的序列。

1、声明数组

数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标(index,或称索引)可以访问数组中的每一个值。例如,如果 a 是一个整型数组,a[i] 就是数组中下标为 i 的整数。

在声明数组变量时,需要指出数组类型(数组元素类型紧跟 [] )和数组变量的名字。下面声明了整型数组 a:int[] a;。

不过,这条语句只声明了变量 a,并没有将 a 初始化为一个真正的数组。应该使用 new 操作符创建数组。

int[] a = new int[100]; // or var a = new int[100]

这条语句声明并初始化了一个可以存储 100 个整数的数组。
数组长度不要求是变量:new int[n] 会创建i一个长度为 n 的数组。

一旦创建了数组,就不能再改变它的长度(不过,当然可以改变单个的数组元素)。如果程序运行中需要经常扩展数组的大小,就应该使用另一种数组结构——数组列表(array list)。

在 Java 中,提供了一种创建数组对象并同时提供初始值的简写形式。下面是一个例子:

int[] smallPrimes = {2, 3, 5, 7 11, 13};

请注意,这个语法中不需要使用 new,甚至不用指定长度。
最后一个值允许有逗号,如果你要不断为数组增加值,这会很方便:

String[] authers = {
	"James Gosling",
	"Bill Joy",
	"Guy Steele",
	// add more names here and put a comma after each name
}

还可以声明一个匿名数组:

new int[] {17, 19, 23, 29, 31, 37}

这会分配一个新数组并填入大括号中提供的值。它会统计初始值个数,并相应的设置数组大小。可以使用这种语法重新初始化一个数组而无须创建新变量。例如:

smallPrimes = new int[] {17, 19, 23, 29, 31, 37};

这是下列语句的简写形式:

int[] anonymous = {17, 19, 23, 29, 31, 37};
smallPromes = anonymous;
2、访问数组元素

创建一个数字数组时,所有元素都初始化为 0。boolean 数组的元素会初始化为 false。对象数组的元素则初始化为一个特殊值 null,表示这些元素(还)未存放任何元素。例如,

String[] names = new String[10];

会创建一个包含 10 个字符串的数组,所有字符串都为 null。如果希望这个数组包含空串,必须为元素指定空串:

for (int i = 0; i < 20; i++) names[i] = "";

要想获得数组中的元素个数,可以使用 array.length。例如,

for (int i = 0; i < a.length; i++)
	System.out.println(i);
3、for each 循环

Java 有一种功能很强的循环结构,可以i用来一次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下标值。

这种增强的 for 循环语句格式为:

for (variable: collection) statement

它定义一个变量用于暂存集合中的每一个元素,并执行相应的语句(当然,也可以是语句块)。collection 这一集合表达式必须是一个数组或者是一个实现了 Iterable 接口的类对象(例如 ArrayList )。例如,

for (int element: a)
	System.out.println(element);

打印数组 a 的每一个元素,一个元素占一行。

当然,使用传统的 for 循环也可以获得同样的效果:

for (int i = 0; i < a.length; i++)
	System.out.println(a[i]);

但是,for each 循环语句显得更加简洁、更不易出错,因为你不必为下标的起始值和终止值而操心。

有一个更加简单的方式可以打印数组中大哥所有值,即利用 Arrays 类的 toString 方法。调用 Arrays.toString(a),返回一个包含数组元素的字符串,这些元素包围在中括号内,并用逗号分隔,例如,”[2, 3, 5, 7, 11,13]”。要想打印数组,只需要调用
System.out.println(Arrays.toString(a))

4、数组拷贝

如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf 方法:

int[] copiedLuckyNumbers = Arrays.copyOf(luckyNumbers, luckyNumbers.length);

第 2 个参数是新数组的长度。这个方法通常用来增加数组的大小:

luckyNumbers = Arrays.copyOf(luckyNumbers, 2 * luckyNumbers.length);

如果数组是数值型,那么额外的元素将被赋值为 0;如果数组元素时布尔型,则将赋值为 false。相反,如果长度小于原始数组的长度,则只拷贝前面的值。

5、数组排序

要想对数值型数组进行排序,可以使用 Arrays 类中的 sort 方法:

int[] a = new int[10000];
...
Arrays.sort(a)

这个方法使用了优化的快速排序(QuickSort)算法。快速排序算法对于大多数数据集合来说都是效率比较高的。

java.util.Arrays

static String toString(xxx[] a)
返回包含 a 中元素的一个字符串,这些元素用中括号包围,并用逗号分隔。在这个方法以及后面的方法中,数组元素类型 xxx 可以是 int、long、char、byte、boolen、float 或 double。static xxx[] copyOf(xxx[] a, int end)static xxx[] copyOfRange(xxx[] a, int start, int end)
返回与 a 类型相同的一个数组,其长度为 length 或者 end-start,数组元素为 a 的值。如果 end 大于 a.length,结果会填充 0 或 false 值。static void sort(xxx[] a)
使用优化的快速排序算法对数组进行排序。static int binarySearch(xxx[] a, xxx v)static int binarySearch(xxx[] a, int start, int end, xxx v)
使用二分查找算法在有序数组 a 中查找值 v。如果找到 v,则返回相应的下标;否则,返回一个负数值 r。-r-1 是 v 应插入的位置(为保持 a 有序)。static void fill(xxx[] a, xxx v)
将数组的所有数据元素设置为 v。static boolean equals(xxx[] a, xxx[] b)
如果两个数组大小相同,并且下标相同的元素都对应相等,返回 true。

现在,我们已经了解了 Java 语言的基本程序结构。下一章将介绍 Java 中最核心的知识点:面向对象。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/776894.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号