Java Doc API 文档

https://docs.oracle.com/en/java/javase/11/docs/api/index.html

Java Math类的常用方法

Java 中的 +、-、*、/ 和 % 等基本算术运算符不能进行更复杂的数学运算,例如,三角函数、对数运算、指数运算等。于是 Java 提供了 Math 工具类来完成这些复杂的运算。

在 Java 中 Math 类封装了常用的数学运算,提供了基本的数学操作,如指数、对数、平方根和三角函数等。Math 类位于 java.lang 包,它的构造方法是 private 的,因此无法创建 Math 类的对象,并且 Math 类中的所有方法都是类方法,可以直接通过类名来调用它们。

下面详细介绍该类的常量及数学处理方法。

静态常量

Math 类中包含 E 和 PI 两个静态常量,正如它们名字所暗示的,它们的值分别等于 e(自然对数)和 π(圆周率)。

例 1
调用 Math 类的 E 和 PI 两个常量,并将结果输出。代码如下:

  1. System.out.println("E 常量的值:" + Math.E);
  2. System.out.println("PI 常量的值:" + Math.PI);

执行上述代码,输出结果如下:

  1. E 常量的值:2.718281828459045
  2. PI 常量的值:3.141592653589793

求最大值、最小值和绝对值

在程序中常见的就是求最大值、最小值和绝对值问题,如果使用 Math 类提供的方法可以很容易实现。这些方法的说明如表 1 所示。

方法 说明
static int abs(int a) 返回 a 的绝对值
static long abs(long a) 返回 a 的绝对值
static float abs(float a) 返回 a 的绝对值
static double abs(double a) 返回 a 的绝对值
static int max(int x,int y) 返回 x 和 y 中的最大值
static double max(double x,double y) 返回 x 和 y 中的最大值
static long max(long x,long y) 返回 x 和 y 中的最大值
static float max(float x,float y) 返回 x 和 y 中的最大值
static int min(int x,int y) 返回 x 和 y 中的最小值
static long min(long x,long y) 返回 x 和 y 中的最小值
static double min(double x,double y) 返回 x 和 y 中的最小值
static float min(float x,float y) 返回 x 和 y 中的最小值

例 2
求 10 和 20 的较大值、15.6 和 15 的较小值、-12 的绝对值,代码如下:

  1. public class Test02 {
  2. public static void main(String[] args) {
  3. System.out.println("10 和 20 的较大值:" + Math.max(10, 20));
  4. System.out.println("15.6 和 15 的较小值:" + Math.min(15.6, 15));
  5. System.out.println("-12 的绝对值:" + Math.abs(-12));
  6. }
  7. }

该程序的运行结果如下:

  1. 1020的较大值:20
  2. 15.615的较小值:15.0
  3. -12的绝对值:12

求整运算

Math 类的求整方法有很多,详细说明如表 2 所示。

方法 说明
static double ceil(double a) 返回大于或等于 a 的最小整数
static double floor(double a) 返回小于或等于 a 的最大整数
static double rint(double a) 返回最接近 a 的整数值,如果有两个同样接近的整数,则结果取偶数
static int round(float a) 将参数加上 1/2 后返回与参数最近的整数
static long round(double a) 将参数加上 1/2 后返回与参数最近的整数,然后强制转换为长整型

例 3
下面的实例演示了 Math 类中取整函数方法的应用:

  1. import java.util.Scanner;
  2. public class Test03 {
  3. public static void main(String[] args) {
  4. Scanner input = new Scanner(System.in);
  5. System.outprintln("请输入一个数字:");
  6. double num = input.nextDouble();
  7. System.out.println("大于或等于 "+ num +" 的最小整数:" + Math.ceil(num));
  8. System.out.println("小于或等于 "+ num +" 的最大整数:" + Math.floor(num));
  9. System.out.println("将 "+ num +" 加上 0.5 之后最接近的整数:" + Math.round(num));
  10. System.out.println("最接近 "+num+" 的整数:" + Math.rint(num));
  11. }
  12. }

执行结果如下:

  1. 请输入一个数字:
  2. 99.01
  3. 大于或等于 99.01 的最小整数:100.0
  4. 小于或等于 99.01 的最大整数:99.0
  5. 99.01 加上 0.5 之后最接近的整数:100
  6. 最接近 99.01 的整数:99.0

三角函数运算

Math 类中包含的三角函数方法及其说明如表 3 所示。

方法 说明
static double sin(double a) 返回角的三角正弦值,参数以孤度为单位
static double cos(double a) 返回角的三角余弦值,参数以孤度为单位
static double asin(double a) 返回一个值的反正弦值,参数域在 [-1,1],值域在 [-PI/2,PI/2]
static double acos(double a) 返回一个值的反余弦值,参数域在 [-1,1],值域在 [0.0,PI]
static double tan(double a) 返回角的三角正切值,参数以弧度为单位
static double atan(double a) 返回一个值的反正切值,值域在 [-PI/2,PI/2]
static double toDegrees(double angrad) 将用孤度表示的角转换为近似相等的用角度表示的角
staticdouble toRadians(double angdeg) 将用角度表示的角转换为近似相等的用弧度表示的角


在表 3 中,每个方法的参数和返回值都是 double 类型,参数以弧度代替角度来实现,其中 1 度等于 π/180 弧度,因此平角就是 π 弧度。
例 4
计算 90 度的正弦值、0 度的余弦值、1 的反正切值、120 度的弧度值,代码如下:

  1. public class Test04 {
  2. public static void main(String[] args) {
  3. System.out.println{"90 度的正弦值:" + Math.sin(Math.PI/2));
  4. System.out.println("0 度的余弦值:" + Math.cos(0));
  5. System.out.println("1 的反正切值:" + Math.atan(l));
  6. System.out.println("120 度的弧度值:" + Math.toRadians(120.0));
  7. }
  8. }

在上述代码中,因为 Math.sin() 中的参数的单位是弧度,而 90 度表示的是角度,因此需要将 90 度转换为弧度,即 Math.PI/180*90,故转换后的弧度为 Math.PI/2,然后调用 Math 类中的 sin() 方法计算其正弦值。

该程序的运行结果如下:

  1. 90 度的正弦值:1.0
  2. 0 的余弦值:1.0
  3. 1 的反正切值:0.7853981633974483
  4. 120 度的弧度值:2.0943951023931953

指数运算

指数的运算包括求方根、取对数及其求 n 次方的运算。在 Math 类中定义的指数运算方法及其说明如表 4 所示。

方法 说明
static double exp(double a) 返回 e 的 a 次幂
static double pow(double a,double b) 返回以 a 为底数,以 b 为指数的幂值
static double sqrt(double a) 返回 a 的平方根
static double cbrt(double a) 返回 a 的立方根
static double log(double a) 返回 a 的自然对数,即 lna 的值
static double log10(double a) 返回以 10 为底 a 的对数

例 5
使用 Math 类中的方法实现指数的运算,main() 方法中的代码如下:

  1. public class Test05 {
  2. public static void main(String[] args) {
  3. System.out.println("4 的立方值:" + Math.pow(4, 3));
  4. System.out.println("16 的平方根:" + Math.sqrt(16));
  5. System.out.println("10 为底 2 的对数:" + Math.log1O(2));
  6. }
  7. }

该程序的运行结果如下:

  1. 4 的立方值:64.0
  2. 16 的平方根:4.0
  3. 10 为底 2 的对数:0.3010299956639812

Java生成随机数(random()和Random类)

在 Java 中要生成一个指定范围之内的随机数字有两种方法:一种是调用 Math 类的 random() 方法,一种是使用 Random 类。

方法 说明
boolean nextBoolean() 生成一个随机的 boolean 值,生成 true 和 false 的值概率相等
double nextDouble() 生成一个随机的 double 值,数值介于 [0,1.0),含 0 而不包含 1.0
int nextlnt(int n) 生成一个随机的 int 值,该值介于 [0,n),包含 0 而不包含 n。如果想生成
指定区间的 int 值,也需要进行一定的数学变换
long nextLong() 返回一个随机长整型数字
boolean nextBoolean() 返回一个随机布尔型值
float nextFloat() 返回一个随机浮点型数字

例1
下面编写一个 Java 程序,演示如何使用 Random 类提供的方法来生成随机数。具体代码如下:

  1. import java.util.Random;
  2. public class Test06 {
  3. public static void main(String[] args) {
  4. Random r = new Random();
  5. double d1 = r.nextDouble(); // 生成[0,1.0]区间的小数
  6. int i1 = r.nextInt(10); // 生成[0,10]区间的整数
  7. boolean b1 = r.nextBoolean(); // 生成一个随机布尔型值
  8. }
  9. }

Java Date类、Calendar类

日期、日历

在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。其中,Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象。下面详细介绍这两个类的具体使用。

Date 类

Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。
1. 构造方法
Date 类构造方法。

  • Date():此种形式表示分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒),使用该构造方法创建的对象可以获取本地的当前时间。

使用示例如下:

  1. Date date1 = new Date(); // 调用无参数构造函数

Date 类的无参数构造方法获取的是系统当前的时间,显示的顺序为星期、月、日、小时、分、秒、年。

  1. 常用方法
    Date 类提供了许多与日期和事件相关的方法,其中常见的方法如表 1 所示。
方法 描述
boolean after(Date when) 判断此日期是否在指定日期之后
boolean before(Date when) 判断此日期是否在指定日期之前
int compareTo(Date anotherDate) 比较两个日期的顺序
boolean equals(Object obj) 比较两个日期的相等性
long getTime() 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来,此 Date 对象表示的毫秒数
String toString() 把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy。
其中 dow 是一周中的某一天(Sun、Mon、Tue、Wed、Thu、Fri 及 Sat)

Calendar 类

Calendar 类是一个抽象类,它为特定瞬间与 YEAR、MONTH、DAY_OF—MONTH、HOUR 等日历字段之间的转换提供了一些方法,并为操作日历字段(如获得下星期的日期) 提供了一些方法。

创建 Calendar 对象不能使用 new 关键字,因为 Calendar 类是一个抽象类,但是它提供了一个 getInstance() 方法来获得 Calendar类的对象。getInstance() 方法返回一个 Calendar 对象,其日历字段已由当前日期和时间初始化。

  1. Calendar c = Calendar.getInstance();

当创建了一个 Calendar 对象后,就可以通过 Calendar 对象中的一些方法来处理日期、时间。Calendar 类的常用方法如表 2 所示。

方法 描述
void add(int field, int amount) 根据日历的规则,为给定的日历字段 field 添加或减去指定的时间量 amount
boolean after(Object when) 判断此 Calendar 表示的时间是否在指定时间 when 之后,并返回判断结果
boolean before(Object when) 判断此 Calendar 表示的时间是否在指定时间 when 之前,并返回判断结果
void clear() 清空 Calendar 中的日期时间值
int compareTo(Calendar anotherCalendar) 比较两个 Calendar 对象表示的时间值(从格林威治时间 1970 年 01 月 01 日
00 时 00 分 00 秒至现在的毫秒偏移量),大则返回 1,小则返回 -1,相等返回 0
int get(int field) 返回指定日历字段的值
int getActualMaximum(int field) 返回指定日历字段可能拥有的最大值
int getActualMinimum(int field) 返回指定日历字段可能拥有的最小值
int getFirstDayOfWeek() 获取一星期的第一天。根据不同的国家地区,返回不同的值
static Calendar getInstance() 使用默认时区和语言坏境获得一个日历
static Calendar getInstance(TimeZone zone) 使用指定时区和默认语言环境获得一个日历
static Calendar getInstance(TimeZone zone,
Locale aLocale)
使用指定时区和语言环境获得一个日历
Date getTime() 返回一个表示此 Calendar 时间值(从格林威治时间 1970 年 01 月 01 日 00 时
00 分 00 秒至现在的毫秒偏移量)的 Date 对象
long getTimeInMillis() 返回此 Calendar 的时间值,以毫秒为单位
void set(int field, int value) 为指定的日历字段设置给定值
void set(int year, int month, int date) 设置日历字段 YEAR、MONTH 和 DAY_OF_MONTH 的值
void set(int year, int month, int date, int hourOfDay,
int minute, int second)
设置字段 YEAR、MONTH、DAY_OF_MONTH、HOUR、 MINUTE 和 SECOND 的值
void setFirstDayOfWeek(int value) 设置一星期的第一天是哪一天
void setTimeInMillis(long millis) 用给定的 long 值设置此 Calendar 的当前时间值


Calendar 对象可以调用 set() 方法将日历翻到任何一个时间,当参数 year 取负数时表示公元前。Calendar 对象调用 get() 方法可以获取有关年、月、日等时间信息,参数 field 的有效值由 Calendar 静态常量指定。

Calendar 类中定义了许多常量,分别表示不同的意义。

  • Calendar.YEAR:年份。
  • Calendar.MONTH:月份。
  • Calendar.DATE:日期。
  • Calendar.DAY_OF_MONTH:日期,和上面的字段意义完全相同。
  • Calendar.HOUR:12小时制的小时。
  • Calendar.HOUR_OF_DAY:24 小时制的小时。
  • Calendar.MINUTE:分钟。
  • Calendar.SECOND:秒。
  • Calendar.DAY_OF_WEEK:星期几。

例如,要获取当前月份可用如下代码:

  1. int month = Calendar.getInstance().get(Calendar.MONTH);

如果整型变量 month 的值是 0,表示当前日历是在 1 月份;如果值是 11,则表示当前日历在 12 月份。

使用 Calendar 类处理日期时间的实例如下:

  1. Calendar calendar = Calendar.getInstance(); // 如果不设置时间,则默认为当前时间
  2. calendar.setTime(new Date()); // 将系统当前时间赋值给 Calendar 对象
  3. System.out.println("现在时刻:" + calendar.getTime()); // 获取当前时间
  4. int year = calendar.get(Calendar.YEAR); // 获取当前年份
  5. System.out.println("现在是" + year + "年");
  6. int month = calendar.get(Calendar.MONTH) + 1; // 获取当前月份(月份从 0 开始,所以加 1)
  7. System.out.print(month + "月");
  8. int day = calendar.get(Calendar.DATE); // 获取日
  9. System.out.print(day + "日");
  10. int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 获取今天星期几(以星期日为第一天)
  11. System.out.print("星期" + week);
  12. int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前小时数(24 小时制)
  13. System.out.print(hour + "时");
  14. int minute = calendar.get(Calendar.MINUTE); // 获取当前分钟
  15. System.out.print(minute + "分");
  16. int second = calendar.get(Calendar.SECOND); // 获取当前秒数
  17. System.out.print(second + "秒");
  18. int millisecond = calendar.get(Calendar.MILLISECOND); // 获取毫秒数
  19. System.out.print(millisecond + "毫秒");
  20. int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); // 获取今天是本月第几天
  21. System.out.println("今天是本月的第 " + dayOfMonth + " 天");
  22. int dayOfWeekInMonth = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH); // 获取今天是本月第几周
  23. System.out.println("今天是本月第 " + dayOfWeekInMonth + " 周");
  24. int many = calendar.get(Calendar.DAY_OF_YEAR); // 获取今天是今年第几天
  25. System.out.println("今天是今年第 " + many + " 天");
  26. Calendar c = Calendar.getInstance();
  27. c.set(2012, 8, 8); // 设置年月日,时分秒将默认采用当前值
  28. System.out.println("设置日期为 2012-8-8 后的时间:" + c.getTime()); // 输出时间

上面的示例代码演示了 Calendar 类中的方法与常量的结合使用,从而完成处理日期的操作。

Java日期格式化(DateFormat类和SimpleDateFormat类)

在 Java 中,可以使用 DateFormat 类和 SimpleDateFormat 类来格式化日期,下面详细介绍这两个格式化日期类的使用。

DateFormat 类

DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期→文本)、解析(文本→日期)和标准化日期。

在创建 DateFormat 对象时不能使用 new 关键字,而应该使用 DateFormat 类中的静态方法 getDateInstance(),示例代码如下:

  1. DateFormat df = DateFormat.getDateInstance();

在创建了一个 DateFormat 对象后,可以调用该对象中的方法来对日期/时间进行格式化。
格式化样式主要通过 DateFormat 常量设置。将不同的常量传入方法中,以控制结果的长度。DateFormat 类的常量如下。

  • SHORT:完全为数字,如 12.5.10 或 5:30pm。
  • MEDIUM:较长,如 May 10,2016。
  • LONG:更长,如 May 12,2016 或 11:15:32am。
  • FULL:是完全指定,如 Tuesday、May 10、2012 AD 或 11:l5:42am CST。


使用 DateFormat 类格式化曰期/时间的示例如下:

  1. // 获取不同格式化风格和中国环境的日期
  2. DateFormat df1 = DateFormat.getDateInstance(DateFormat.SHORT, Locale.CHINA);
  3. DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL, Locale.CHINA);
  4. DateFormat df3 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);
  5. DateFormat df4 = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA);
  6. // 获取不同格式化风格和中国环境的时间
  7. DateFormat df5 = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.CHINA);
  8. DateFormat df6 = DateFormat.getTimeInstance(DateFormat.FULL, Locale.CHINA);
  9. DateFormat df7 = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.CHINA);
  10. DateFormat df8 = DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA);
  11. // 将不同格式化风格的日期格式化为日期字符串
  12. String date1 = df1.format(new Date());
  13. String date2 = df2.format(new Date());
  14. String date3 = df3.format(new Date());
  15. String date4 = df4.format(new Date());
  16. // 将不同格式化风格的时间格式化为时间字符串
  17. String time1 = df5.format(new Date());
  18. String time2 = df6.format(new Date());
  19. String time3 = df7.format(new Date());
  20. String time4 = df8.format(new Date());
  21. // 输出日期
  22. System.out.println("SHORT:" + date1 + " " + time1);
  23. System.out.println("FULL:" + date2 + " " + time2);
  24. System.out.println("MEDIUM:" + date3 + " " + time3);
  25. System.out.println("LONG:" + date4 + " " + time4);

运行该段代码,输出的结果如下:

  1. SHORT18-10-15 上午9:30
  2. FULL20181015 星期一 上午093043 CST
  3. MEDIUM2018-10-15 9:30:43
  4. LONG20181015 上午093043

该示例主要介绍了 DateFormat 类中方法与常量的结合使用,通过使用 DateFomat 类可以对日期进行不同风格的格式化。

SimpleDateFormat 类(常用)

如果使用 DateFormat 类格式化日期/时间并不能满足要求,那么就需要使用 DateFormat 类的子类——SimpleDateFormat。

SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类,它允许进行格式化(日期→文本)、解析(文本→日期)和规范化。SimpleDateFormat 使得可以选择任何用户定义的日期/时间格式的模式。

SimpleDateFormat 类主要有如下 3 种构造方法。

  • SimpleDateFormat():用默认的格式和默认的语言环境构造 SimpleDateFormat。
  • SimpleDateFormat(String pattern):用指定的格式和默认的语言环境构造 SimpleDateFormat。
  • SimpleDateFormat(String pattern,Locale locale):用指定的格式和指定的语言环境构造 SimpleDateFormat。

SimpleDateFormat 自定义格式中常用的字母及含义如表 2 所示。

字母 含义 示例
y 年份。一般用 yy 表示两位年份,yyyy 表示 4 位年份 使用 yy 表示的年扮,如 11;
使用 yyyy 表示的年份,如 2011
M 月份。一般用 MM 表示月份,如果使用 MMM,则会
根据语言环境显示不同语言的月份
使用 MM 表示的月份,如 05;
使用 MMM 表示月份,在 Locale.CHINA
语言环境下,如“十月”;在 Locale.US
语言环境下,如 Oct
d 月份中的天数。一般用 dd 表示天数 使用 dd 表示的天数,如 10
D 年份中的天数。表示当天是当年的第几天, 用 D 表示 使用 D 表示的年份中的天数,如 295
E 星期几。用 E 表示,会根据语言环境的不同, 显示不
同语言的星期几
使用 E 表示星期几,在 Locale.CHINA 语
言环境下,如“星期四”;在 Locale.US 语
言环境下,如 Thu
H 一天中的小时数(0~23)。一般用 HH 表示小时数 使用 HH 表示的小时数,如 18
h 一天中的小时数(1~12)。一般使用 hh 表示小时数 使用 hh 表示的小时数,如 10 (注意 10 有
可能是 10 点,也可能是 22 点)
m 分钟数。一般使用 mm 表示分钟数 使用 mm 表示的分钟数,如 29
s 秒数。一般使用 ss 表示秒数 使用 ss 表示的秒数,如 38
S 毫秒数。一般使用 SSS 表示毫秒数 使用 SSS 表示的毫秒数,如 156

例 1
编写 Java 程序,使用 SimpleDateFormat 类格式化当前日期并打印,日期格式为“xxxx 年 xx 月 xx 日星期 xxx 点 xx 分 xx 秒”,具体的实现代码如下:

  1. import java.text.SimpleDateFormat;
  2. import java.util.Date;
  3. public class Test13 {
  4. public static void main(String[] args) {
  5. Date now = new Date(); // 创建一个Date对象,获取当前时间
  6. // 指定格式化格式
  7. SimpleDateFormat f = new SimpleDateFormat("今天是 " + "yyyy 年 MM 月 dd 日 E HH 点 mm 分 ss 秒");
  8. System.out.println(f.format(now)); // 将当前时间袼式化为指定的格式
  9. //Date d2 = format.parse("2022-03-16 23:44:24");
  10. }
  11. }

该程序的运行结果如下:

  1. 今天是 2018 10 15 星期一 09 26 23

Java数字格式化(DecimalFormat)

DecimalFormat 是 NumberFormat 的一个子类,用于格式化十进制数字。DecimalFormat 类包含一个模式和一组符号,常用符号的说明如表 1 所示。

符号 说明
0 显示数字,如果位数不够则补 0
# 显示数字,如果位数不够不发生变化

例 1
下面编写一个 Java 程序,演示如何使用 DecimalFormat 类将数字转换成各种格式,实现代码如下。

  1. //.后面的0,不够补0
  2. DecimalFormat format1 = new DecimalFormat("0.000");
  3. //,###:三个一组分割
  4. //.#后面不够不补充,
  5. DecimalFormat format2 = new DecimalFormat(",###.###");
  6. double d = 11232321100.6;
  7. System.out.println(format1.format(d));
  8. System.out.println(format2.format(d));

Java String 类

字符串是 Java 中特殊的类,使用方法像一般的基本数据类型,被广泛应用在 Java 编程中。Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个 String 类来创建和操作字符串。

在 Java 中定义一个字符串最简单的方法是用双引号把它包围起来。这种用双引号括起来的一串字符实际上都是 String 对象,如字符串“Hello”在编译后即成为 String 对象。因此也可以通过创建 String 类的实例来定义字符串。

不论使用哪种形式创建字符串,字符串对象一旦被创建,其值是不能改变的,但可以使用其他变量重新赋值的方式进行更改。

直接定义字符串

直接定义字符串是指使用双引号表示字符串中的内容,例如“Hello Java”、“Java 编程”等。具体方法是用字符串常量直接初始化一个 String 对象,示例如下:

  1. String str = "Hello Java";

或者

  1. String str;
  2. str = "Hello Java";

注意:字符串变量必须经过初始化才能使用。
例 1
下面的实例演示了直接创建字符串的几种用法。

  1. String str = "我是一只小小鸟"; // 结果:我是一只小小鸟
  2. String word = "I am a bird"; // 结果:I am a bird
  3. word = "Let\'s say that it\'s true"; // 结果:Let's say that it's true
  4. System.out.println(word);
  5. word = "北京\\上海\\广州"; // 结果:北京\上海\广州

使用 String 类定义

前面我们提到在 Java 中每个双引号定义的字符串都是一个 String 类的对象。因此,可以通过使用 String 类的构造方法来创建字符串,该类位于 java.lang 包中。

String 类的构造方法有多种重载形式,每种形式都可以定义字符串。下面介绍最常用的几种形式。

1. String()

初始化一个新创建的 String 对象,表示一个空字符序列。

2. String(String original)

初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列。换句话说,新创建的字符串是该参数字符串的副本。例如:

  1. String str1 = new String("Hello Java");
  2. String str2 = new String(str1);

这里 str1 和 str2 的值是相等的。

3. String(char[ ]value)

分配一个新的字符串,将参数中的字符数组元素全部变为字符串。该字符数组的内容已被复制,后续对字符数组的修改不会影响新创建的字符串。例如:

  1. char a[] = {'H','e','l','l','0'};
  2. String sChar = new String(a);
  3. a[1] = 's';

上述 sChar 变量的值是字符串“Hello”。 即使在创建字符串之后,对 a 数组中的第 2 个元素进行了修改,但未影响 sChar 的值。

4. String中常用的方法

length()

字符串的长度

  1. String a = "Hello Word!";
  2. System.out.println(a.length);
  3. //输出的结果是字符串长度10。

charAt()

截取一个字符

  1. String a = "Hello Word";
  2. System.out.println(a.charAt(1));
  3. //输出的结果是字符串a的下标为1的字符e。

getBytes()

将字符串变成一个byte数组

  1. String a = "Hello Word";
  2. byte b[] = a.getBytes();
  3. System.out.println(new String(b));
  4. //输出的结果为Hello Word的byte数组。

toCharArray()

将字符串变成一个字符数组

  1. String a = "Hello Word";
  2. char[]b = a.toCharArray();
  3. System.out.println(b);
  4. //输出的结果为Hello Word字符数组。

equals()和equalsIgnoreCase():常用的

比较两个字符串是否相等,前者区分大小写,后者不区分

  1. String a = "Hello Word";
  2. String b = "hello word";
  3. System.out.println(a.equals(b));
  4. System.out.println(a.equalsIgnoreCase(b));
  5. //输出的结果为第一条为false,第二条为true。

startsWith()和endsWith()

判断字符串是不是以特定的字符开头或结束

  1. String a = "Hello Word";
  2. System.out.println(a.startsWith("ee"));
  3. System.out.println(a.endsWith("rd"));
  4. //输出的结果第一条为false,第二条为true。

toUpperCase()和toLowerCase()

将字符串转换为大写或小写

  1. String a = "Hello Word";
  2. System.out.println(a.toUpperCase());
  3. System.out.println(a.toLowerCase());

输出的结果第一条为“HELLO WORD”,第二条为“hello word”。

trim()

去掉起始和结束的空格

  1. String a = " Hello Word ";
  2. System.out.println(a.trim());
  3. //输出的结果为“Hello Word”。

substring()

截取字符串

  1. String a = "Hello Word";
  2. System.out.println(a.substring(0, 5));
  3. System.out.println(a.substring(6));
  4. //输出的结果第一条为“Hello”,第一个参数0(beginIndex)
  5. //是开始截取的位置,第二个参数5(endIndex)是截取结束的位置
  6. //输出的结果第二条是“Word”,参数6(beginIndex)是开始截取的位置。

indexOf()和lastIndexOf()

前者是查找字符或字符串第一次出现的地方,后者是查找字符或字符串最后一次出现的地方

  1. String a = "Hello Word";
  2. System.out.println(a.indexOf("o"));
  3. System.out.println(a.lastIndexOf("o"));
  4. //输出的结果第一条是4,是o第一次出现的下标,第二条是7,是o最后一次出现的下标。

replace()

替换

  1. String a = "Hello Word";
  2. String b = "你好";
  3. System.out.println(a.replace(a, b));
  4. System.out.println(a.replace(a, "HELLO WORD"));
  5. System.out.println(b.replace("你", "大家"));
  6. //输出的结果第一条为“你好”,第二条为“HELLO WORD”,第三条为“大家好”。

split()

字符串分割

  1. String name = "张三";
  2. System.out.println(name.split("")[0]);//张
  3. System.out.println(name.split("")[1]);//三
  4. String info = "我,热,爱Java编程";
  5. String[] infos = info.split(",");//[我,热,爱Java编程]
  6. for (String s : infos) {
  7. System.out.println(s);
  8. }

Java String:字符串常量池

作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么?
代码:从字符串常量池中获取相应的字符串

  1. String str1 = "hello";//将字符串存储到常量池中
  2. String str2 = "hello";//拿到的是上面的hello
  3. System.out.println("str1 == str2 -> " + (str1 == str2) ); //true
  4. String str3 = new String("hello");//新创建对象,存储在堆中
  5. Systme.out.println(str1 == str3);//false

04_Java常用API - 图1

StringBuffer和StringBuilder

StringBuffer

StringBuffer称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer是可变对象,这个是String最大的不同

  1. public class StringBufferTest01 {
  2. public static void main(String[] args) {
  3. StringBuffer sbStr = new StringBuffer();
  4. for (int i=0; i<100; i++) {
  5. //sbStr.append(i);
  6. //sbStr.append(",");
  7. //方法链的编程风格
  8. sbStr.append(i).append(",");
  9. //拼串去除逗号
  10. //sbStr.append(i);
  11. //if (i != 99) {
  12. // sbStr.append(",");
  13. //}
  14. }
  15. //可以输出
  16. System.out.println(sbStr);
  17. System.out.println("");
  18. System.out.println(sbStr.toString());
  19. System.out.println("");
  20. //去除逗号
  21. System.out.println(sbStr.toString().substring(0,sbStr.toString().length()-1));
  22. System.out.println("");
  23. System.out.println(sbStr.substring(0, sbStr.length()-1));
  24. }
  25. }

StringBuilder

用法同StringBuffer,StringBuilder和StringBuffer的区别是StringBuffer中所有的方法都是同步的,是线程安全的,但速度慢,StringBuilder的速度快,但不是线程安全的

String、StringBuilder、StringBuffer对比

1.可变与不可变

String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。
private final char value[];
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。
char[] value;

2.是否多线程安全

String中的对象是不可变的,也就可以理解为常量,显然线程安全。
AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的

StringBuilder与StringBuffer共同点

StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。
抽象类与接口的其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。
StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(…)。只是StringBuffer会在方法上加synchronized关键字,进行同步。
最后,如果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。

正则表达式

一、String字符串匹配

  1. //public boolean matches(String regex):判断是否与正则表达式匹配,匹配返回true
  2. // 只能是 a b c
  3. System.out.println("a".matches("[abc]")); // true
  4. System.out.println("z".matches("[abc]")); // false
  5. // 不能出现a b c
  6. System.out.println("a".matches("[^abc]")); // false
  7. System.out.println("z".matches("[^abc]")); // true
  8. System.out.println("a".matches("\\d")); // false
  9. System.out.println("3".matches("\\d")); // true
  10. System.out.println("333".matches("\\d")); // false
  11. System.out.println("z".matches("\\w")); // true
  12. System.out.println("2".matches("\\w")); // true
  13. System.out.println("21".matches("\\w")); // false
  14. System.out.println("你".matches("\\w")); //false
  15. System.out.println("你".matches("\\W")); // true
  16. System.out.println("---------------------------------");
  17. //以上正则匹配只能校验单个字符。
  18. // 校验密码
  19. // 必须是数字 字母 下划线 至少 6位
  20. System.out.println("2442fsfsf".matches("\\w{6,}"));
  21. System.out.println("244f".matches("\\w{6,}"));
  22. // 验证码 必须是数字和字符 必须是4位
  23. System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));
  24. System.out.println("23_F".matches("[a-zA-Z0-9]{4}"));
  25. System.out.println("23dF".matches("[\\w&&[^_]]{4}"));
  26. System.out.println("23_F".matches("[\\w&&[^_]]{4}"));
  27. System.out.print("请输入密码:");
  28. Scanner scanner = new Scanner(System.in);
  29. String password = scanner.next();
  30. if(password.matches("\\w{2,10}")){
  31. System.err.println("密码符合规范");
  32. }else{
  33. System.err.println("密码不符合规范");
  34. }

二、String的replace、split

正则表达式在方法中的应用。
public String[] split(String regex):
— 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。
public String replaceAll(String regex,String newStr)
— 按照正则表达式匹配的内容进行替换

  1. String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";
  2. String[] arrs = names.split("\\w+");
  3. for (int i = 0; i < arrs.length; i++) {
  4. System.out.println(arrs[i]);
  5. }
  6. String names2 = names.replaceAll("\\w+", " ");
  7. System.out.println(names2);
  8. //将数字都给删除
  9. String str = "fdsfds3432432fdsfds564654dfsgfd564654";
  10. str = str.replaceAll("\\d+","");
  11. System.out.println(str);

三、匹配提取

java.util.regex 包主要包括以下三个类:

  • Pattern 类:pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
  • Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
  • PatternSyntaxException:PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

以下实例中使用了正则表达式 .abc. 用于查找字符串中是否包了 abc 子串:

  1. public static void main(String[] args){
  2. String content = "I am abc from abcdef.com.";
  3. String pattern = ".*abcdef.*";
  4. boolean isMatch = Pattern.matches(pattern, content);
  5. System.out.println("字符串中是否包含了 'abcdef' 子字符串? " + isMatch);
  6. }
  1. String rs = "你好,我的邮箱是12sdfds3456@qq.com,fdsfa@432fds.mm手机号是17312341234";
  2. // 需求:从上面的内容中爬取出 电话号码和邮箱。
  3. // 1、定义爬取规则,字符串形式
  4. String regex = "(\\w{0,20}@\\w{0,6}\\.\\w{2,6})|(\\d{11})";
  5. // 2、把这个爬取规则编译成匹配对象。
  6. Pattern pattern = Pattern.compile(regex);
  7. // 3、得到一个内容匹配器对象
  8. Matcher matcher = pattern.matcher(rs);
  9. // 4、开始找了
  10. while (matcher.find()) {
  11. String rs1 = matcher.group();
  12. System.out.println(rs1);
  13. }

四、匹配规则

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html

  1. 字符类
  2. [abc] a, b, c(简单类)
  3. [^abc] a除, b, c(否定)以外的任何字符
  4. [a-zA-Z] a通过z A通过Z,包括(范围)
  5. [a-d[m-p]] a通过d,或m通过p:([a-dm-p]联合)
  6. [a-z&&[def]] d, e, or f(intersection)
  7. [a-z&&[^bc]] a通过z,除了bc:([ad-z]减法)
  8. [a-z&&[^m-p]] a通过z,而不是m通过p:([a-lq-z]减法
  9. 预定义的字符类
  10. . 任何字符(可能与行终止符匹配,也可能不匹配)
  11. \d 一个数字:[0-9]
  12. \D 非数字:[^0-9]
  13. \h 水平空白字符: [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]
  14. \H 非水平空白字符:[^\h]
  15. \s 空白字符:[ \t\n\x0B\f\r]
  16. \S 非空白字符:[^\s]
  17. \v 垂直空白字符:[\n\x0B\f\r\x85\u2028\u2029]
  18. \V 非垂直空白字符:[^\v]
  19. \w 一个字字符:[a-zA-Z_0-9]
  20. \W 非单词字符:[^\w]
字符 说明
\ 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n匹配字符 n\n 匹配换行符。序列 \\\\ 匹配 \\\\( 匹配 (
^ 匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与”\n”或”\r”之后的位置匹配。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与”\n”或”\r”之前的位置匹配。
* 零次或多次匹配前面的字符或子表达式。例如,zo 匹配”z”和”zoo”。 等效于 {0,}。
+ 一次或多次匹配前面的字符或子表达式。例如,”zo+”与”zo”和”zoo”匹配,但与”z”不匹配。+ 等效于 {1,}。
? 零次或一次匹配前面的字符或子表达式。例如,”do(es)?”匹配”do”或”does”中的”do”。? 等效于 {0,1}。
{n} n 是非负整数。正好匹配 n 次。例如,”o{2}”与”Bob”中的”o”不匹配,但与”food”中的两个”o”匹配。
{n,} n 是非负整数。至少匹配 n 次。例如,”o{2,}”不匹配”Bob”中的”o”,而匹配”foooood”中的所有 o。”o{1,}”等效于”o+”。”o{0,}”等效于”o*”。
{n,m} mn 是非负整数,其中 n <= m。匹配至少 n 次,至多 m 次。例如,”o{1,3}”匹配”fooooood”中的头三个 o。’o{0,1}’ 等效于 ‘o?’。注意:您不能将空格插入逗号和数字之间。
? 当此字符紧随任何其他限定符(*、+、?、{n}、{n,}、{n,m})之后时,匹配模式是”非贪心的”。”非贪心的”模式匹配搜索到的、尽可能短的字符串,而默认的”贪心的”模式匹配搜索到的、尽可能长的字符串。例如,在字符串”oooo”中,”o+?”只匹配单个”o”,而”o+”匹配所有”o”。
. 匹配除”\r\n”之外的任何单个字符。若要匹配包括”\r\n”在内的任意字符,请使用诸如”[\s\S]”之类的模式。
(pattern) 匹配 pattern 并捕获该匹配的子表达式。可以使用 $0…$9 属性从结果”匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用”\(“或者”\)”。
(?:pattern) 匹配 pattern 但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用”or”字符 (|) 组合模式部件的情况很有用。例如,’industr(?:y|ies) 是比 ‘industry|industries’ 更经济的表达式。
(?=pattern) 执行正向预测先行搜索的子表达式,该表达式匹配处于匹配 pattern 的字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?=95|98|NT|2000)’ 匹配”Windows 2000”中的”Windows”,但不匹配”Windows 3.1”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
(?!pattern) 执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如,’Windows (?!95|98|NT|2000)’ 匹配”Windows 3.1”中的 “Windows”,但不匹配”Windows 2000”中的”Windows”。预测先行不占用字符,即发生匹配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。
x|y 匹配 xy。例如,’z|food’ 匹配”z”或”food”。’(z|f)ood’ 匹配”zood”或”food”。
x&y 匹配 x 并且 y。”ab”.matches(“[a&b]+”)->true
[xyz] 字符集。匹配包含的任一字符。例如,”[abc]”匹配”plain”中的”a”。
[^xyz] 反向字符集。匹配未包含的任何字符。例如,”[^abc]”匹配”plain”中”p”,”l”,”i”,”n”。
[a-z] 字符范围。匹配指定范围内的任何字符。例如,”[a-z]”匹配”a”到”z”范围内的任何小写字母。
[^a-z] 反向范围字符。匹配不在指定的范围内的任何字符。例如,”[^a-z]”匹配任何不在”a”到”z”范围内的任何字符。
\b 匹配一个字边界,即字与空格间的位置。例如,”er\b”匹配”never”中的”er”,但不匹配”verb”中的”er”。
\B 非字边界匹配。”er\B”匹配”verb”中的”er”,但不匹配”never”中的”er”。
\cx 匹配 x 指示的控制字符。例如,\cM 匹配 Control-M 或回车符。x 的值必须在 A-Z 或 a-z 之间。如果不是这样,则假定 c 就是”c”字符本身。
\d 数字字符匹配。等效于 [0-9]。
\D 非数字字符匹配。等效于 [^0-9]。
\f 换页符匹配。等效于 \x0c 和 \cL。
\n 换行符匹配。等效于 \x0a 和 \cJ。
\r 匹配一个回车符。等效于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等。与 [ \f\n\r\t\v] 等效。
\S 匹配任何非空白字符。与 [^ \f\n\r\t\v] 等效。
\t 制表符匹配。与 \x09 和 \cI 等效。
\v 垂直制表符匹配。与 \x0b 和 \cK 等效。
\w 匹配任何字类字符,包括下划线。与”[A-Za-z0-9_]”等效。
\W 与任何非单词字符匹配。与”[^A-Za-z0-9_]”等效。
\xn 匹配 n,此处的 n 是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如,”\x41”匹配”A”。”\x041”与”\x04”&”1”等效。允许在正则表达式中使用 ASCII 代码。
\num 匹配 num,此处的 num 是一个正整数。到捕获匹配的反向引用。例如,”(.)\1”匹配两个连续的相同字符。
\n 标识一个八进制转义码或反向引用。如果 \n 前面至少有 n 个捕获子表达式,那么 n 是反向引用。否则,如果 n 是八进制数 (0-7),那么 n 是八进制转义码。
\nm 标识一个八进制转义码或反向引用。如果 \nm 前面至少有 nm 个捕获子表达式,那么 nm 是反向引用。如果 \nm 前面至少有 n 个捕获,则 n 是反向引用,后面跟有字符 m。如果两种前面的情况都不存在,则 \nm 匹配八进制值 nm,其中 n m 是八进制数字 (0-7)。
\nml n 是八进制数 (0-3),ml 是八进制数 (0-7) 时,匹配八进制转义码 nml
\un 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。