Java的基本程序设计(2)

【本文概述】本节我们主要讲述Java中字符串String类相应的方法,接着总结了编程中常用的控制流程语句,最后介绍了Java中一个特殊的大数类。

2.1 字符串

从概念上讲,Java字符串就是Unicode字符序列。Java并没有内置字符串类型,而是在标准库中提供了一个预定义类String。每个用双引号括起来的字符串都是String类的实例:

1
2
String str = ""; // empty string
String greet = "Hello";

2.1.1 子串

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

1
2
3
// str.substring(begin, end) -> str[begin] -- str[end-1]
String greet = "Hello";
String subgreet = greet.substring(0, 3); // Hel

2.1.2 拼接

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

1
2
3
String name = "nxlyx";
String age = "20";
String message = name + age; // nxlyx20

当将一个字符串与一个非字符串的值进行拼接时,后者会转换成字符串,正如之前所说的将一个数值转换成一个字符串只需要+ ""即可。

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

1
String strjoin = String.join("/", "S", "M", "L"); // S/M/L

如果需要将一个字符串重复多次,可以使用repeat方法。

1
String strrepeat = "Java".repeat(2); // JavaJava

2.1.3 字符串不可变

与C语言不同的地方在于,Java中String类没有提供修改字符串中某个字符的方法,也不能修改,因此将String类对象称为是不可变的。不过,不能修改一个字符串的某个字符,不代表不能修改字符串,我们可以通过提取想要保留的子串,再与希望替换的字符拼接,从而得到希望的字符。

1
greet = greet.substring(0, 3) + "P!" // Help!

通过修改字符串变量,让它引用另外一个字符串就可以很方便的修改字符串,同时Java会自动回收弃用的垃圾字符串,这一点也方便了程序员的操作。

Java中字符串更类似于C语言中的char*指针,而不是一个字符数组。

java字符串不可变

2.1.4 检测字符串相等

可以使用equals方法检测两个字符串是否相等,

1
s.equals(t)

如果字符串s与字符串t相等,则返回true;否则,返回false。需要注意的是st既可以是字符串变量,也可以是字符串字面量。

1
"Hello".equals(t)

若是希望检测两个字符串是否相等,且不区分大小写,可以使用equalsIgnoreCase方法。但一定要记住不能使用==检测两个字符串是否相等。这个运算符只能够确定两个字符串是否存放在同一个位置上。

  • 代码单元是计算机内部用于存储和处理文本数据的最小单元,其大小取决于所使用的编码方案。

  • 码点是 Unicode 中的基本字符抽象,是一个唯一的整数值,通常以十六进制表示。同一个码点在不同的编码方案中可能由不同数量的代码单元表示。

2.1.5 String API

这里我们汇总一部分常用的字符串方法。当然,如果有需要可以查阅Java的API文档:https://docs.oracle.com/javase/9/docs/api/overview-summary.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 一般不要用char这个类型,除非你非常清楚自己在干什么
char charAt(int index);
// 按照字典顺序,如果字符串位于other之前,返回一个负数;
// 如果位于other之后,返回一个正数;相等则返回0
int compareTo(String other);
// 判断字符串是否为空或者由空格组成,返回true
boolean empty();
boolean blank();
// 如果字符串与other相等,返回true
boolean equals(Object other);
// 如果字符串与other相等(忽略大小写),返回true
boolean equalsIgnoreCase(String other);
// 返回与字符串str匹配的第一个子串开始的位置
// 从索引0或者fromindex开始匹配。如果不存在,则返回-1
int indexOf(String str);
int indexOf(String str, int fromindex);
// 返回与字符串str匹配的最后一个子串开始的位置
// 从末尾或者fromindex开始匹配。如果不存在,则返回-1
int lastIndexOf(String str);
int lastIndexOf(String str, int fromindex);
// 返回字符串代码单元的个数
int length();
// 用新字符串代替原始字符串中所有的老字符串
String replace(CharSequence oldString, CharSequence newString);
// 返回一个新字符串,取出子串
String substring(int begin);
String substring(int begin, int end);
// 将所有字母改为大写字母或小写字母
String toUpperCase();
String toLowerCase();
// 返回一个新字符串,用给定界定符连接所有元素
String join(CharSequence delimiter, CharSequence... elements);
// 返回一个字符串,将当前字符串重复count次
String repeat(count);

2.1.6 构建字符串

有些时候,我们需要拼接的字符串数量极多,同时可能还需要极其复杂的插入顺序,这是用传统的+运算就不太适合了。因此,在Java中还有一种比较全面的字符串构建方法,StringBuilder类。

如果需要用许多小段的字符串来构建一个字符串,应该按照下面步骤进行:

首先构建一个空的字符串构建器:StringBuilder builder = new StringBuilder()

接着每次按照需要添加内容:builder.append(ch)

最终构建完成后,调用toString方法,将可以得到一个String对象:String str = builder.toString()

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

1
2
3
4
5
6
7
8
9
10
11
12
// 构建新的字符串构建器
StringBuilder();
// 返回构建器中代码单元数量
int length();
// 追加一个字符串
StringBuilder append(String str);
// 在offset位置插入一段字符串
StringBuilder insert(int offset, String str);
// 将start到end-1的代码单元删除
StringBuilder delete(int begin, int end);
// 返回一个与构建器中内容相同的字符串
String toString();

当然还有一种办法就是使用静态的String.format方法创建一个格式化的字符串,而不打印输出:

1
Stringmessage = String.format("Hello, $s. Next year you'll be %d", name, age);

2.2 控制流程

与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流程。这部分比较简单,在这里我们以极快的速度介绍条件和循环语句。

2.2.1 条件语句

在Java中,条件语句的形式为:if (condition) statement,这里的条件必须用小括号括起来,假如条件为真时有多条语句需要执行,我们就可以使用块语句,例如:

1
2
3
4
if (yourAge > 18) {
yourstate = 1;
System.out.println(yourstate);
}

更一般地,如果有多个条件时,我们就可以使用:if (condition1) ... else if (condition2)... else...,例如:

1
2
3
4
5
6
7
8
9
if (yourAge < 18) {
yourstate = 0;
}
else if (yourAge < 60) {
yourstate = 1;
}
else {
yourstate = 2;
}

2.2.2 循环语句

程序设计中使用的循环语句分为whilefor两种。这里我们分别来介绍一下。

首先是while语句,形式为:while (condition) statement。如果条件为true就会执行statement中的内容;否则就会退出循环。

1
2
3
while (balance < goal) {
balance += payment;
}

或者还有一种do...while语句,形式为:do statement while (condition);。这种循环语句会先执行一次statement中的内容,然后检测循环条件。如果为true,就重复执行语句,然后再次检测循环条件,直至不符合条件,退出循环。

1
2
3
do {
balance += payment;
} while (balance < goal);

接着我们来看for语句。这是一种可以确定循环次数的语句形式:for (...; ...; ...) {...}for语句中的第一部分通常是对计数器初始化;第二部分给出每次新一轮循环执行前需要检测的循环条件;第三部分指定如何更新计数器。

1
2
3
for (int i = 10; i > 0; --i) {
System.out.println(i);
}

2.2.3 多重选择语句

在处理多个选项时,使用if/else结构显得不够灵活。Java中有一个和C中一样的switch语句。switch语句将从与选项值相匹配的case标签开始执行,直到遇到break语句,或者执行到结束处为止。如果没有相匹配的case标签,而有default子句,就执行这个子句。

switch中有一个相当危险的情况,就是触发了多个case语句。这往往是因为没有加break语句导致的。

1
2
3
4
5
6
7
8
9
10
11
switch (i) {
case 1:
...;
break;
case 2:
...;
break;
default:
...;
break;
}

2.2.4 中断控制流程

这里我们要介绍的实际上就是我们之前已经体现过的breakcontinue语句。这两者都是比较简单的语句形式,在此就不赘述了,大家可以通过下面的代码了解一下。

1
2
3
4
for (int i = 0; i < n; ++i) {
if (i == 2) continue; // 如果i等于2, 那么直接进入下一轮循环(条件依旧需要判断)
if (i == n / 2) break; // 如果i等于n / 2, 那么直接结束循环
}

2.3 大数

如果基本的整数和浮点数精度不能够满足需求,那么可以使用java.math包中两个比较有用的类:BigIntegerBigDecimal

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

1
BigInteger a = BigInteger.valueOf(100);

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

1
BigInteger reallyBig = new BigInterger("243234523452954823742510525012313214");

由于不能使用一般的算术运算符来处理大数,所以 Java 提供了大数运算方法:(这里仅给两个示例)

1
2
BigInteger c = a.add(b);
BigInteger d = c.multiply(b.add(BigInteger.valueOf(2)));

除此之外,还有一些别的运算方法:

1
2
3
4
5
6
7
8
BigInteger add(BigInteger other);
BigInteger subtract(BigInteger other);
BigInteger multiply(BigInteger other);
BigInteger divide(BigInteger other);
BigInteger mod(BigInteger other);
BigInteger sqrt();
int compareTo(BigInteger other);
static BigInteger valueOf(long x);
1
2
3
4
5
6
7
8
9
10
BigDecimal add(BigDecimal other);
BigDecimal subtract(BigDecimal other);
BigDecimal multiply(BigDecimal other);
BigDecimal divide(BigDecimal other);
// RoungingMode.HALF_UP四舍五入
BigDecimal divide(BigDecimal other, RoundingMode mode);
int compareTo(BigDecimal other);
// 返回值等于x或x/10^scale的一个大实数
static BigDecimal valueOf(long x);
static BigDecimal valueOf(long x, int scale);