# Java教程 - 2 基础语法

# 2.1 Java程序说明

在学习基础语法之前,先对 Java 程序进行一个简单的说明。

在 Java 中,关于功能的代码都是写在类中的,至于什么是类,面向对象的章节再讲解。

在 HelloWorld 的程序中,我们首先创建了一个 HelloWorld.java 文件,在文件中编写了如下代码:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
1
2
3
4
5

代码中的 class 后面的 HelloWorld 就是类名,在一个 *.java 文件中是可以定义多个类的:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

class Person {
    
}

class Animal {
    
}
1
2
3
4
5
6
7
8
9
10
11
12
13

在上面的代码中,我们在一个类中定义类 3 个类。

但是注意

  • 在一个 Java 源文件中,可以声明多个class,但是只能最多有一个类声明为 public 的;
  • 声明为 public 的类的类名必须与 *.java 源文件名称相同,在上面 HelloWorld 类是 public 的,所以 文件名必须为 HelloWorld.java
  • 程序编译完成,会发现一个类会生成一个 .class 文件,所以一个 Java 源文件可能会对应多个 .class 文件。

关于打印语句

上面使用 System.out.println() 来打印 HelloWorld 。其实还有一个 System.out.print()

System.out.print()System.out.println() 都是打印数据的,println() 表示打印完数据后,会换行,所以如果在 println() 后面继续打印的话,会在第二行打印。

举个栗子:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("name:");
        System.out.println("Doubi");
    }
}
1
2
3
4
5
6

执行结果为:

name:
Doubi
1
2

修改一下程序:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.print("name:");
        System.out.println("Doubi");
    }
}
1
2
3
4
5
6

执行结果为:

name:Doubi
1

再修改一下程序:

public class HelloWorld {
    public static void main(String[] args) {
        System.out.print("name:");
        System.out.println();
        System.out.print("Doubi");
    }
}
1
2
3
4
5
6
7

System.out.println() 可以不输出内容,单纯用来换行,所以上面代码的执行结果:

name:
Doubi
1
2

# 2.2 注释

我们在学习任何语言,都会有注释,注释的作用:就是向别人解释我们编写的代码的含义和逻辑,使代码有更好的可读性。

其实更重要的是给自己看的,过了一个月,看之前自己的代码,只会有一个疑问,这是狗写的?

注释不是程序,是不会被编译的,也是不会被执行的

在 Java 中注释分类三类,单行注释多行注释文档注释

# 1 单行注释

单行注释以 // 开头,// 号右边为注释内容。

例如:

public class HelloWorld {
    public static void main(String[] args) {
        // 打印:Hello World!
        System.out.println("Hello World!");
    }
}
1
2
3
4
5
6

注意:// 号和注释内容一般建议以一个空格隔开,这是代码规范,建议大家遵守。

单行注释一般用于对一行或一小部分代码进行解释。

# 2 多行注释

多行注释是以 /* */ 括起来,中间的内容为注释内容,注释内容可以换行。

public class HelloWorld {
    public static void main(String[] args) {
        /*
        打印语句,可以多行
        Hello World!
         */
        System.out.println("Hello World!");
    }
}

1
2
3
4
5
6
7
8
9
10

多行注释一般用于描述一段代码或者变量的详细信息。

# 3 文档注释

如果你是初学者,先简单了解一下即可。

文档注释使用 /** 开始,*/ 结束。这种注释方式常用于生成API文档,可以包含对类、方法和属性的描述。

举个栗子:

/**
 * 第一个 Java 程序,HelloWorld
 * @author Doubi
 * @version V1.0.0
 * @date 2023-10-10
 */
public class HelloWorld {

    /**
     * 程序入口方法
     * @param args 方法参数
     */
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

文档注释中的标签通常以 @ 符号开头,用于描述作者、版本、类、参数、返回值等详细信息。这些注释可以由文档生成工具(如javadoc)用来生成文档以供开发者参考。

例如上面的注释,我们可是使用 IDEA 来生成文档,在 IDEA 中,选择 Tools --> Generate JavaDoc...

然后填写生成文档的配置:

然后点击生成,会在配置的目录生成文档。然后在电脑上的目录中找到生成的文档,会包含一个 index.html ,双击打开文件,显示内容格式如下:

可以看到我们在代码中写的文档注释的内容。这就是文档注释的作用。

# 2.3 变量和常量

在代码中,数据是保存在哪里的呢?

在代码中,数据需要保存在变量中,变量是在程序运行的时候存储数据用的,可以想象变量为一个盒子。

整数、浮点数(小数)、字符串(文本)都可以放在变量中。

数据有不同的类型,例如我们保存姓名,使用的的是字符串,也就是文本,但是保存年龄,是数字类型,金额可能使用的小数的类型,不同的数据会使用不同的数据类型来保存,所以不同的数据需要使用定义不同类型的变量来存储。

# 1 定义变量

所以我们现在定义变量来保存数据。

定义变量的格式:类型 变量名 = 值;

public class HelloJava {
    public static void main(String[] args) {
        String name = "Doubi"; // 定义一个字符串变量,用来存储姓名
        int age = 18;          // 定义一个整数变量
        double height = 1.78;  // 定义一个浮点数类型

        // 定义完变量就可以使用变量了
        System.out.println(name);       // Doubi
        System.out.println(age);        // 18
        System.out.println(height);     // 1.78
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

在上面的代码中,我们分别使用了不同的类型定义了不同类型的数据,使用 String 定义字符串类型,使用 int 定义整形数,使用 double 定义浮点数,使用 = 给变量赋值。

Java 是强类型语言,就是每个变量都要指明类型。


变量被定义后,就可以在后面的代码中使用了,而且还可以重新修改变量的值。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        int age = 18;
        age = 12;
        int year = age;

        System.out.println(age);       // 12
        System.out.println(year);      // 12
    }
}
1
2
3
4
5
6
7
8
9
10

在上面的中,我们可以重新修改变量的值,而且可以使用一个变量给另一个变量赋值。


变量在使用之前一定要初始化,初始化就是赋值。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        int age;        // 声明变量
        //System.out.println(age);      // 代码报错,age没有初始化
        
        age = 12;				// 对变量进行赋值,也就初始化了
        System.out.println(age);        // 初始化了,可以使用
    }
}
1
2
3
4
5
6
7
8
9

在上面的代码中,int age; 只是声明变量,并没有初始化变量,是没有默认值的,在使用变量之前,需要对变量进行初始化。

# 2 交换两个变量的值

交换两个变量的值需要借助第三个变量。

public class HelloJava {
    public static void main(String[] args) {
        int a = 2;
        int b = 3;

        // 需要借助第三个变量,
        int temp = b;   // 将b的值赋值给temp
        b = a;          // 将a的值赋值给b
        a = temp;       // 将temp的值赋值给a

        System.out.println(a);  // 3
        System.out.println(b);  // 2
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3 变量的作用域

什么是变量的作用域?

变量的作用域就是变量的使用范围,不可能我定义了一个变量,在哪里都能使用。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        //System.out.println(number);        // 无法访问number
    }

    public static void test() {
        int number = 12;
    }
}
1
2
3
4
5
6
7
8
9

在上面的代码中,number 是定义在 test() 方法中的,只能在 test() 方法中使用,在 main 方法中是没办法访问的。

也就是说一个变量只能在它所在的 {} 内使用,当然如果 {} 内还有 {},在内部的 {} 也是可以使用的。

另外在同一个作用域内,不能定义同名的变量,流入在 test() 方法中只能定义一个变量叫 number

# 4 常量

变量的值是可以变的,就像上面我们定义了变量,后面可以修改它的值。

常量就是值不能改变的。

在 Java 中,使用 final 关键字来定义常量。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        final int age = 18;
        age = 12;           // 报错,age是常量,初始化完成是没有办法修改的。
    }
}
1
2
3
4
5
6

使用const定义的常量也可以使用final来定义,但是使用 const 定义,这有助于优化性能和节省内存。

另外需要注意的是,常量和变量的类型可以显式指定,也可以通过类型推断来自动推断。例如:

// 使用 const 关键字定义常量,并显式指定类型为 int
const int a = 10;

// 使用 const 关键字定义常量,并自动推断类型为 int
const b = 20;
1
2
3
4
5

# 2.4 标识符

什么是标识符?

标识符就是名字,例如变量的名字、方法的名字、类的名字等等。

起名字肯定会有限制,肯定不能 张Three 这样起名字,所以标识符也有限制。

# 1 标识符命名规则

标识符需要遵守一下规则:

  1. 只能是英文、数字、下划线,其他任何内容都不允许;
  2. 不能使用数字开头,可以英文或下划线开头;
a					// 可以
a_b				// 可以
_a				// 可以
a1				// 可以
a_b_a			// 可以

1					// 错误
1_				// 错误
1_a				// 错误
1
2
3
4
5
6
7
8
9
  1. 大小写敏感,大小写不同是不同的标识符;
// # name 和 Name 是不同的标识符
String name = "Doubi";
String Name = "Niubi";		
1
2
3
  1. 不能使用关键字,关键字就是 Java 中保留的一些单词,有特殊的用途,不能被用作标识符;

Java 中有如下关键字:

abstract assert boolean break byte case catch
char class continue default do double else
enum extends final finally float for if
implements import int interface instanceof long native
new package private protected public return short
static strictfp super switch synchronized this throw
throws transient try void volatile while true
false null goto const

这么多怎么记?不用记!不用记!不用记!

后面每个关键字都会学到,自然知道每个关键字是做什么用的,不用记!

# 2 变量命名规范

使用上面说的规则,我们可以定义变量名了。

但是为了优雅、统一、规范,我们在定义变量名时,还应该遵守以下规范,虽然你不遵守,没人开枪打死你,但是建议你遵守。

  1. 见名知意

看见一个变量名,就知道这个变量名是干嘛的。

String a = "zhangsan";								// 看到a,鬼知道a是干嘛的
String name = "zhangsan";							// 看到name,就知道这是个名字,简单明了
String onePersonName = "zhangsan";		// 在确保明了的前提下,尽量减少长度,这个有点不够简洁
1
2
3
  1. 类名使用首字母大写的驼峰规则
class BankAccount {}
class ShoppingCartItem {}
1
2
  1. 变量使用首字母小写的驼峰规则
String name;
String accountNumber;
1
2

# 2.5 数据类型

# 1 整型

整型就是整数。

下面这些都是整数:

123
1234567
123456789101112L  		// 表示长整型,需要以L作为后缀
123L  								// 表示长整型
0x0F									// 十六进制形式整数
0b00001011						// 二进制形式的整数
1
2
3
4
5
6

Java 中表示整数的类型有 byte、short、int、long。

它们的区别就是占用内存空间的大小,也就是保存数据的大小。

  • byte:8 位有符号整数,也就是1个字节,取值范围为 -128 到 127。
  • short:16 位有符号整数,也就是2个字节,取值范围为 -32768 到 32767。
  • int:32 位有符号整数,也就是4个字节,取值范围为-21,4748,3648 到 21,4748,3647,通常是最常用的整数类型
  • long:64 位有符号整数,也就是8个字节,取值范围为-9223372036854775808 到 9223372036854775807,用于表示大整数值,例如时间戳(从1970年1月1日0时开始到指定时间的毫秒数)。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        byte b = 127;
        short s = 123;
        int i = 123456;
        long l = 12345678910L;     // 必须以L或l结尾

        System.out.println(i);
    }
}
1
2
3
4
5
6
7
8
9
10

通常,定义整型数据,用的最多的就是 int,定义 long 类型,需要使用 Ll 结尾。

# 2 浮点型

浮点型就是小数。

下面这些都是浮点数。

123.5					// 默认就是双精度浮点数
123.5e10			// 科学计数法,表示123.5乘以10的10次方,平时用的不多
123.5f				// 单精度浮点数,后面需要加f后缀
1
2
3

Java 中表示浮点型的类型有 float、double。

它们的区别是占用内存空间大小不同、保存数据的范围不同、表示数据的精度不同。

  • float:32 位单精度浮点数,4个字节,用于表示小数,有约 6-7 位有效数字。
  • double:64 位双精度浮点数,8个字节,用于表示双精度小数,有约 15-16 位有效数字。
public class HelloJava {
    public static void main(String[] args) {
        float f = 12.34F;   // 定义float类型,需要以F或f结尾
        double d = 12.34;

        System.out.println(d);
    }
}
1
2
3
4
5
6
7
8

定义float类型,变量要以 Ff 结尾,通常情况下,我们定义浮点数,一般都使用 double

# 3 字符类型

字符类型就是表示一个字符。例如:

'A'
'a'
'#'
'3' 	// 这不是整数,是一个字符
'我'
1
2
3
4
5

表示字符的类型是 char:

  • char:16 位 Unicode 字符,2个字节,用于表示单个字符,例如字母、数字或符号。

举个例子:

public class HelloJava {
    public static void main(String[] args) {
        char c1 = 'A';
        char c2 = '1';
        char c3 = '逗';

        char c4 = '\n';     // 转义字符,表示换行符
        char c5 = '\t';     // 制表符,也就是tab键

        char c6 = '\u9017';

        System.out.println(c6); // 逗
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

刚才说 char 只能表示一个字符,为什么上面的代码有的是多个字符呢?

这是因为 Java 中所有的字符都是使用 Unicode 编码的,所以一个字符可以存储一个字母、汉字或者其他的书面的一个字符。

\uXXXX 表示的就是一个 Unicode 字符,XXXX表示的是十六进制整数,上面的 \u9017 对应的汉字就是 ,这种方式用的不多。

Unicode 其实就是一个字符集,字符集就是不同的编号对应不同的字符、符号、汉字等等,通过这个编号可以找到对应的字符。

因为计算机只能存储二进制数字0和1,所以显示文本的时候,需要将数字转换为字符,然后进行显示。计算机是人家老美发明的,他家才用几个字符呀,26个英文字母大小写,再加上数字和一些符号,200个绰绰有余,所以他们整了一个ASCII码表,拿到一个数字,例如97,然后去ASCII表里面找对应的字符,一看对应A,然后显示A。

但是其他国家也要用计算机呀,各个国家文字又不一样,于是每个语言弄了一个字符集,但是又遇到一个问题,同样一个数字在不同的字符集对应的字符是不一样的,这样就导致我打开文档的时候字符集不对,显示的内容就不对,会乱码。

怎么办呢,搞一个Unicode字符集,包括各个国家的语言,但是Unicode字符集有缺点,就是规定了字符的二进制代码,但是没规定如何存储,没法知道三个字节存储的是一个三个字节的字符还是三个一个字节的字符。即使规定所有的字符都用三个字节存储,对于只需要一个字节就可以存储的字符,例如英文字母,也是空间上的浪费。

所以现在用的最广的是UTF-8字符集,它是一种变长的编码方式,使用1-6个字节表示一个字符,支持各个语言,如果我们都用这个字符集来保存和读取数据,就不会出现乱码问题了。


char 除了是一个字符,其实还是一个数字。

举个例子:

public class HelloJava {
    public static void main(String[] args) {
        char c1 = 'a';
        char c2 = 97;

        System.out.println(c1);     // a
        System.out.println(c2);     // a
    }
}
1
2
3
4
5
6
7
8
9

可以将一个数字赋值给 char ,打印的时候,发现上面的 c1 和 c2 的结果都是 a

还是上面说的,97 在Unicode 编码中对应的是 a,其实更准确的说法是 97 在ASCII 编码中对应的是 a,只是 ASCII 码是 Unicode 编码的一个子集。

实际使用中,很少将数字赋值给 char,这里知道一下可以这样就行了。

# 4 boolean类型

boolean 表示布尔值,它的值只有两个,只能取 truefalse

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        boolean loginSuccess = false;
        loginSuccess = true;
        System.out.println(loginSuccess);   // true
    }
}
1
2
3
4
5
6
7

boolean值一般用作判断,当然判断语句后面会学习,现在只是举个例子:

public class HelloJava {
    public static void main(String[] args) {
        boolean loginSuccess = false;
        if (loginSuccess) {
            System.out.println("登录成功");   
        }
        else {
            System.out.println("登录失败");   
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11

上面使用 boolean 值,用过 if 的判断条件,如果为 true,就执行 if后面 {} 括号中的内容,如果为 false,就执行 else 后面 {} 括号的内容。

一般我们也是通过运算,得到布尔值的结果,然后再使用 boolean 值做判断。

# 5 字符串类型

字符串类型不是基本数据类型,是引用数据类型,也是最常用的数据类型了,用来存储文本数据。在 Java 中,可以使用双引号 " 来定义字符串:

下面这些都是字符串:

"abcdefg"
"Hello World!"
"我爱你中国"
1
2
3

在 Java 中字符串类型是 String 类型,可以存储任意的字符序列。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        String name = "Doubi";
        String website = "www.doubibiji.com";

        System.out.println(name);   // Doubi
        System.out.println(website);    // www.doubibiji.com
    }
}
1
2
3
4
5
6
7
8
9

String 可以存储任意的文本数据,而且还提供了一些方法,后面再介绍。

# 2.6 数据类型转换

Java 数据类型之间是可以进行转换的。byte、short、int、long、float、double、char,这7个数据可以相互转换。

# 1 自动类型转换

我们可以直接将容量小的类型赋值给容量大的类型。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        byte b = 12;
        short s = b;
        char c = 13;
        int i = s;      // short 赋值给int
        i = c;          // char 赋值给 int
        long l = i;     // int 赋值给 long
        float f = l;    // long 赋值给 float
        double d = f;   // float 赋值给 double

        i = b;		// byte可以赋值给更大的int
        d = i;		// int可以赋值给更大的double

        System.out.println(d);      // 12.0
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

在上面的代码中,我们可以将容量小的数据类型的变量赋值给大的数据类型的变量,不用做额外的操作。但是反过来就不行了。

需要注意:

float 类型表示的数据范围是比 long 类型的范围还大的,虽然 long 是8个字节,float 是是4个字节存储,但是 float 会丢失精度。

虽然 char 是两个字节,但是 byteshort 是无法直接赋值给 char 的。

当容量小的数据类型的变量和容量大的数据类型的变量做运算时,结果自动提升为容量大的数据类型。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        byte b = 12;
        int i = 13;

        int sum = b + i;
        System.out.println(sum);      // 25
    }
}
1
2
3
4
5
6
7
8
9

在上面的代码中,我们将 byte 类型与 int 类型相加,赋值给 sum,这里的 sum 需要定义为 int 类型,当然也可以定义为 long、float、double更大的类型,但是不能定义为比 int 更小的类型。

但是需要注意:当byte、char、short三种类型的变量做运算时,结果为int类型。

查看下面的代码:

public class HelloJava {
    public static void main(String[] args) {
        byte b = 12;
        short s = 13;
        char c = 'a';

        int sum1 = b + s;
        int sum2 = s + c;
        System.out.println(sum1);      // 25
        System.out.println(sum2);      // 110
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

在上面的代码中,我们将 byte 与 short 进行运算,即使是 byte + byte,都需要使用 int 存储结果,char 本质上是数字,也是可以进行运算的。

所以基本数据类型提升的顺序:char、byte、short --> int --> long --> float --> double

boolean 类型是不能与其它数据类型进行转换和运算的。

# 2 强制类型转换

将容量大的类型赋值给容量小的类型,则需要强制类型转换。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        double d = 2.98;
        int i = (int) d;						// 需要在前面添加 (类型) 进行强制转换
        System.out.println(i);      // 3
    }
}
1
2
3
4
5
6
7

浮点型(float、double)转换为整型(byte、short、int、long、char),小数部分会被截掉,而且不会四舍五入,会造成精度损失。


转换之前要确认是否超出范围,因为 byte 是一个字节,表示的范围是: -128 ~ 127,如果我们将 128 赋值给 byte,则也会造成精度损失,导致结果不正确。

举个例子:

int i = 128;
byte b = (byte) i;
System.out.println(b);      // -128
1
2
3

上面将 int 类型 128 的赋值给 byte,结果变成了 -128 , 为什么呢? 这就涉及到二进制数的表示问题了,可以去学习计算机基础知识的课程。

# 2.7 字符串扩展

# 1 字符串长度

通过 .length() 方法可以获取字符串的长度。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        String name = "Doubi";
        System.out.println(name.length());      // 5
    }
}
1
2
3
4
5
6

上面通过 name 调用 .length() 可以获取字符串的长度。

通过 .xxxx(参数) 这样的方式就是调用方法,所以 System.out.println() 中的 .println() 也是调用了方法,方法后面会讲。这里只需要知道调用指定的方法会得到指定的结果。

# 2 字符串初始化

前面讲解变量的时候,变量在使用前必须初始化。

而字符串不是基本数据类型,是引用类型,引用类型的初始化值可以是 null

什么是 null ?

null 表示什么都没有,是空。注意和 "" 的区别;

"" 表示的是一个空的字符串,它是一个字符串,这是没有内容;

" " 表示的是一个空格字符串,字符串的内容是一个空格,注意这三个的区别。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        String str1 = "";
        String str2 = " ";
        String str3 = null;

        System.out.println(str1.length());      // 0
        System.out.println(str2.length());      // 1
        System.out.println(str3.length());      // 报错:NullPointerException
    }
}
1
2
3
4
5
6
7
8
9
10
11

上面三个变量都初始化了,所以就可以使用了。但是当一个变量为 null 的时候,是不用通过它来调用方法的,否则程序会报错。

# 3 转义字符

字符串是用双引号括起来的,但如果我们的字符串中包含双引号,该怎么处理呢?

那就需要使用转义符 \ ,在引号前面加上 \ 表示后面的字符是普通字符串:

String str1 = "Hello \"Doubi\"";
1

同样,如果要输出 \\n\t 等字符也是需要转义符的

String str1 = "Hello \\t Doubi";
String str2 = "Hello \\ Doubi";
String str3 = "Hello \\n Doubi";
1
2
3

因为 \t 是制表符,\n 是换行符,\ 是转义符,如果想在字符串输出这些特殊字符,需要使用 斜杠 \ 进行转义。

# 4 字符串拼接

方式1:使用加号 + 拼接

字符串和所有数据类型都可以直接使用 加号+ 拼接。

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        String hello = "Hello";
        String doubi = "Doubi";
        String helloDoubi = hello + doubi;      // 直接使用 + 进行字符拼接
        System.out.println(helloDoubi);         // 输出: HelloDoubi
      

        System.out.println("Hello" + 3);        // 输出:Hello3,可以和基本数据类型进行拼接
        System.out.println(3.14f + "Hello");    // 输出:3.14Hello
        
        System.out.println(3 + 4 + "Hello");    // 输出:7Hello,前面是数字,从左到右运算,所以先相加
        System.out.println("Hello" + 3 + 4);    // 输出:Hello34,前面是字符串,从左到右,那么变成字符串拼接
        System.out.println("Hello" + (3 + 4));  // 输出:Hello7,如果想要进行数学运算,可以使用括号括起来
        System.out.println('a' + 1 + "Hello");  // 输出:98Hello,'a'是字符
        System.out.println("Hello" + 'a' + 1);  // 输出:Helloa1
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

在上面的中,可以使用 + 号拼接字符串和基本数据类型。注意代码是从左到右运行的,所以要注意是字符串连接还是先进行基本数据类型的运算。


方式2:使用 concat() 方法

举个栗子:

String str1 = "Hello";
String str2 = "Doubi";

String result = str1.concat(", ").concat(str2).concat("!");
System.out.println(result); // 输出: Hello, Doubi!
1
2
3
4
5

通过字符串的 .concat() 方法,可以将两个字符串拼接在一起,多次调用可以多次拼接。


方式3:使用 String.format() 方法

举个栗子:

String name = "doubibiji";
int age = 1;

String formattedString = String.format("Hello, my name is %s and I'm %d years old.", name, age);
System.out.println(formattedString);  // 输出: Hello, my name is doubibiji and I'm 1 years old.
1
2
3
4
5

%s%d 是占位符,和后面的参数对应。%s 表示格式化字符串, %d 表示格式化整数,如果对格式没有要求,可以都使用 %s


方式4:使用 StringBuilderStringBuffer

举个栗子:

public class HelloJava {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();  // 创建StringBuilder
        stringBuilder.append("Hello");
        stringBuilder.append(", ");
        stringBuilder.append("World");
        stringBuilder.append("!");
        
        String result = stringBuilder.toString();       // 将StringBuilder转换为String
        System.out.println(result); // 输出: Hello, World!
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

上面使用的是 StringBuilder 类,通过 append() 方法,也可以使用 StringBuffer 类,用法是完全一样的。StringBuffer是线程安全的 ,StringBuilder不是线程安全的,线程安全后面讲解线程在讲解。如果在方法中定义的变量,例如现在是在 main 方法中定义的变量,所以使就不存在线程安全问题,使用 StringBuilder 即可,比 StringBuffer 性能更好。

这三种方式拼接字符串有什么不同呢?

  1. + 操作符:在简单的情况下是最直观和易于阅读的,但在大量字符串拼接时性能可能较差。每次使用 + 操作符时,都会创建新的 String ,不是在原来的字符串上追加,如果拼接的字符串很多,会导致大量对象的创建和内存操作,性能较差。
  2. concat() 方法:和 + 操作符类似,每次调用 concat() 方法都会创建新的 String 对象,因此性能也不太理想,特别是在大量拼接字符串时。
  3. StringBuilder:性能较好,特别是在需要大量字符串拼接的情况下。因为StringBuilder 是可变的,可以通过 append() 方法一次次地添加字符串,最后通过 toString() 方法获取最终的字符串。因为 StringBuilder 不会像前两种方法那样频繁地创建新的字符串对象,所以在性能上更为优越。如果想要现场安全,则使用 StringBuffer

所以在有大量字符串拼接的情况下,使用 StringBuilderStringBuffer 类,提高性能。

# 5 浮点数格式化

在输出浮点数的时候,我们可以指定输出的浮点数的精度。

举个栗子:

double number = 1.2489;

String formattedNumber = String.format("%.2f", number);     // %.2f表示保留小数点后两位
System.out.println(formattedNumber); // 输出: 1.25
1
2
3
4

注意,使用 String.format 方法将浮点数格式化为固定位数的小数,结果会四舍五入。