数学运算和C的math标准库相似；字符与字符窜与C的差别很大。

## 1. 数学运算

数学运算库（API）所涵盖的东西很多，包括：取整、三角函数、幂运算、矩阵等，这里我们只讨论该库的基本使用和常用函数。

对标准库而言，我们最关心的是什么？一般是三个问题：

1. 基本数据结构
2. 常量
3. 函数

这一章暂时不设计基数据结构，数据结构在另外的章节专门讲解。这里的重点是：

1. 常量 PI
2. 取整函数
3. 随机数函数：Rounding Methods
4. min, max, abs, and random Methods

### 1.1. 取整函数

1. double ceil(double x) x round up to its nearest integer. This integer is  returned as a double value.
2. double floor(double x) x is rounded down to its nearest integer. This integer is  returned as a double value.
3. double rint(double x) x is rounded to its nearest integer. If x is equally close to two integers, the even one is returned as a double.
4. int round(float x) Return (int)Math.floor(x+0.5).
5. long round(double x) Return (long)Math.floor(x+0.5).  

实例：

```java
Math.ceil(2.1) returns 3.0 
Math.ceil(2.0) returns 2.0
Math.ceil(-2.0) returns –2.0
Math.ceil(-2.1) returns -2.0
Math.floor(2.1) returns 2.0
Math.floor(2.0) returns 2.0
Math.floor(-2.0) returns –2.0
Math.floor(-2.1) returns -3.0
Math.rint(2.1) returns 2.0
Math.rint(2.0) returns 2.0
Math.rint(-2.0) returns –2.0
Math.rint(-2.1) returns -2.0
Math.rint(2.5) returns 2.0
Math.rint(-2.5) returns -2.0
Math.round(2.6f) returns 3 
Math.round(2.0) returns 2   
Math.round(-2.0f) returns -2   
Math.round(-2.6) returns -3
```

### 1.2. min, max, and abs

1. max(a, b)and min(a, b) Returns the maximum or minimum of two parameters.
2. abs(a) Returns the absolute value of the parameter.
3. random() Returns a random double value in the range \[0.0, 1.0). 

实例：

```java
Math.max(2, 3) returns 3 
Math.max(2.5, 3) returns 3.0 
Math.min(2.5, 3.6) returns 2.5 
Math.abs(-2) returns 2
Math.abs(-2.1) returns 2.1
```

### 1.3. The random Method

`Math.random();` 函数生成一个0～1之间的double类型的数，包含0,但是不包含1。

## 2. 字符类型

Java有专有的char类型，这个类型和C的字符类型是不同的。只需要记住Java的字符类型支持Unicode就可以了，关于char类型，不是我们讨论的重点。

char对应的类类型（包装类型）是Character。

char类型是有序的（类似整形），整形可以使用的运算符都可以使用在 char 上面。 

### 2.1. char和整形的转换

```java
int i = 'a'; // Same as int i = (int)'a';
char c = 97; // Same as char c = (char)97;
```

### 2.2. char的比较

```java
        if (ch >= 'A' && ch <= 'Z')
            System.out.println(ch + " is an uppercase letter");
        else if (ch >= 'a' && ch <= 'z')
            System.out.println(ch + " is a lowercase letter");
        else if (ch >= '0' && ch <= '9')
            System.out.println(ch + " is a numeric character");
```

### 2.3. 字符类型的相关函数

![](img/20230303171401.png)

上述这些函数不能直接调用，而是在 Character 这个类中，因此如果你要调用上述的函数，需要使用 Character.xxx 这样的方式。所有的函数都是静态函数，静态函数，关于静态函数我们会在学习类的时候进行学习，目前我们用到的都是静态函数。

## 3. 字符串

### 3.1. 字符串的初始化和赋值

字符串与C完全不一样，Java中的字符串的类型是 String 。注意，以前在Java中出现的类型都是小写开头的，这是第一个大写开头的，因此这个是一个类的类型，而不是普通类型。前面讲到过，类是抽象描述（类似结构体指针），如果来实例化（成为可操作的对象）需要使用new 操作生成一个对象。这里我们看看字符串是如何生成的。

```java
public class Main {
    public static void main(String[] args) {
        String s1 = new String("Hello");
        System.out.println(s1);
    }
}
```

第三行代码是生成一个字符串对象，第四行是打印这个字符串。等等，这里和Hello world程序好像有所不同？对的，标准的对象生成应该是按照第三行的方式生成，不过因为String在程序中使用得太频繁了，因此如果写入字符串的字面量，编译器会自动构造一个对象，下面的代码也是正确的：

```java
public class Main {
    public static void main(String[] args) {
        String s1 = "Hello";
        System.out.println(s1);
    }
}
```

或者直接使用字面量作为参数：

```java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello");
    }
}
```

### 3.2. 字符串操作

既然字符串是一个对象，那么就可以用对象的方式来操作字符串。在上述例子中，试试在 s1 这个变量后面输入一个点（.），Eclipse将提示该对象上面的属性和方法（有括号的是方法\\函数，没有括号的是属性\\对象中的变量）。

#### 3.2.1. 字符串对象的基本操作函数

![](img/20230303171623.png)

上述这些函数是在数据库对象上面进行调用的，例如：

```java
        String sA = "Hello world!";
        int len = sA.length();
        char c = sA.charAt(1);
        String sB = sA.toUpperCase();
        String sC = sA.trim();
```

这里不可能解释所有字符串对象的函数，请参考在线文档。

#### 3.2.2. 字符串连接

字符串连接可以使用算术运算符（+），也可以使用对象函数：

```java
        String sA = "Hello";
        String sB = "World";
        System.out.println(sA.concat(" ").concat(sB).concat("!"));
        System.out.println(sA + " " + sB + "!");
```

**注意，concat 函数返回的是字符串对象，因此concat函数后面可以使用任何的字符串对象的函数。**

另外，字符串可以和数值类型的变量或者是字面量进行连接：

```java
public class Main {
    public static void main(String[] args) {
        String sA = "Hello";
        System.out.println(sA + ":" + 3.14 + ":" + 1);
    }
}
```

**其实，字符串可以和几乎所有类型的变量或者字面量进行连接，这一点我们在后面还会遇到。更多的原理要我们学了类的继承才能理解。**

#### 3.2.3. 从控制台读取字符串

前面学习了如何从控制台读取数值类型的值，这里我们看看如何读取字符串/字符。

```java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        String s1 = input.next();        
        String s2 = input.next();
        String s3 = input.next();        

        System.out.println("s1 is " + s1);
        System.out.println("s2 is " + s2);
        System.out.println("s3 is " + s3);        
    }
}
```

运行一下这个代码，输入三个个字符串，字符串间需要使用空格分割，看看结果是什么？

next() 是以空格区分字符串的，如果我们需要读取一段字符串，本身包含空格，这就需要使用 nextLine() 这个函数。试试把next() 改成 nextLine() 会是什么结果。nextLine()是以回车进行区分的。

#### 3.2.4. 字符串比较

这些函数都是只能在对象上面进行操作的，想一想为什么？

![](img/20230303171902.png)

#### 3.2.5. 子串操作

你可以把字符串看作是特殊的数组，使用索引来切取一个字符串的子串，注意，索引时从0开始的。

![](img/20230303171922.png)

![](img/20230303171931.png)

#### 3.2.6. 字符或者是子串查找

![](img/20230303171948.png)

**这里会发现很多函数名是一样的，Java使用参数来具体决定调用哪一个函数，这种方式叫做函数重载（overload），后面我们会具体学到函数重载的技术。简单说来，函数重载是指可以通过传输参数来唯一确定一个同名函数的技术；这就要求同名函数的参数个数不一样，或者是类型不一样。**

#### 3.2.7. 字符串与数字的转换

字符串转换成相应的数值类型：

这时我们需要使用到相应数值类型的类类型（包装类型），而不是简单的类型了。关于包装类型我们后面会讲到，这里先了解一下。

```java
public class Main {
    public static void main(String[] args) {
        int a = Integer.parseInt("1");
        int b = Integer.valueOf("2");
        float c = Float.parseFloat("2.2");
        float d = Float.valueOf("2.2");
    }
}
```

这里 Interger 或者是 Float 是一个类，而非对象。我们把在类上面可以直接调用的方法（不需要实例化成对象），叫做静态方法。关于静态方法，后面学到类的时候还会讲解。

**parseXXX 方法和 valueOf 方法都可以返回相应字符串对应的数值类型（看你是在哪个类型上调用的），区别是 valueOf 返回的是包装类型，parseXXX返回的是基本类型。**

**Integer.parseInt 函数当字符串是代表一个小数的时候会产生异常（运行时错误）；同时所有的转换函数当字符串表达的不是一个数值的时候也会产生异常，例如"1a"、"a1.1a"等。**

数值类型转换成字符串

有很多方式，最简单的是加上一个空字符串（没有内容的字符串），例如：

```java
String sA = 100 + "";
```

#### 3.2.8. 格式化字符串

格式化字符串如同C语言的printf方法，甚至连占位符和格式方法都一模一样。如果要输出一个字符串，可以使用 System.out.printf 方法。

```java
public class Main {
    public static void main(String[] args) {
        System.out.printf("Hello, my name is %s, and %d years old.\n", "Danny", 20);
    }
}
```

当然，如果不想输出字符串，而需要对中间的结果进行格式化应该如何？

```java
public class Main {
    public static void main(String[] args) {
        String a = String.format("Hello, my name is %s, and %d years old.\n", "Danny", 20);
        System.out.print(a);
    }
}
```

下面是占位符列表：

![](img/20230303172243.png)

## 4. 本章重点

1. 数学类：PI常量、取整、随机、最大、最小、绝对值等常用静态函数；
2. 字符类型：
   1. 字符类型声明
   2. unicode（了解）
   3. 字符与整形的关系（与C一致）
3. 字符类型操作函数（静态函数）
4. 字符串（字符串是对象，不是基本类型）
   1. 声明与使用
   2. 基本函数：
      1. length()
      2. charAt(index)
      3. concat(s1)
      4. toUpperCase()
      5. toLowerCase()
      6. trim()
   3. 字符串比较函数
   4. 获取子串
   5. 查找字符串
   6. 字符串与数值的转换