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 两个常量,并将结果输出。代码如下:
System.out.println("E 常量的值:" + Math.E);System.out.println("PI 常量的值:" + Math.PI);
执行上述代码,输出结果如下:
E 常量的值:2.718281828459045PI 常量的值: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 的绝对值,代码如下:
public class Test02 {public static void main(String[] args) {System.out.println("10 和 20 的较大值:" + Math.max(10, 20));System.out.println("15.6 和 15 的较小值:" + Math.min(15.6, 15));System.out.println("-12 的绝对值:" + Math.abs(-12));}}
该程序的运行结果如下:
10和20的较大值:2015.6和15的较小值:15.0-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 类中取整函数方法的应用:
import java.util.Scanner;public class Test03 {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.outprintln("请输入一个数字:");double num = input.nextDouble();System.out.println("大于或等于 "+ num +" 的最小整数:" + Math.ceil(num));System.out.println("小于或等于 "+ num +" 的最大整数:" + Math.floor(num));System.out.println("将 "+ num +" 加上 0.5 之后最接近的整数:" + Math.round(num));System.out.println("最接近 "+num+" 的整数:" + Math.rint(num));}}
执行结果如下:
请输入一个数字:99.01大于或等于 99.01 的最小整数:100.0小于或等于 99.01 的最大整数:99.0将 99.01 加上 0.5 之后最接近的整数:100最接近 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 度的弧度值,代码如下:
public class Test04 {public static void main(String[] args) {System.out.println{"90 度的正弦值:" + Math.sin(Math.PI/2));System.out.println("0 度的余弦值:" + Math.cos(0));System.out.println("1 的反正切值:" + Math.atan(l));System.out.println("120 度的弧度值:" + Math.toRadians(120.0));}}
在上述代码中,因为 Math.sin() 中的参数的单位是弧度,而 90 度表示的是角度,因此需要将 90 度转换为弧度,即 Math.PI/180*90,故转换后的弧度为 Math.PI/2,然后调用 Math 类中的 sin() 方法计算其正弦值。
该程序的运行结果如下:
90 度的正弦值:1.00 的余弦值:1.01 的反正切值:0.7853981633974483120 度的弧度值: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() 方法中的代码如下:
public class Test05 {public static void main(String[] args) {System.out.println("4 的立方值:" + Math.pow(4, 3));System.out.println("16 的平方根:" + Math.sqrt(16));System.out.println("10 为底 2 的对数:" + Math.log1O(2));}}
该程序的运行结果如下:
4 的立方值:64.016 的平方根:4.010 为底 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 类提供的方法来生成随机数。具体代码如下:
import java.util.Random;public class Test06 {public static void main(String[] args) {Random r = new Random();double d1 = r.nextDouble(); // 生成[0,1.0]区间的小数int i1 = r.nextInt(10); // 生成[0,10]区间的整数boolean b1 = r.nextBoolean(); // 生成一个随机布尔型值}}
Java Date类、Calendar类
日期、日历
在 Java 中获取当前时间,可以使用 java.util.Date 类和 java.util.Calendar 类完成。其中,Date 类主要封装了系统的日期和时间的信息,Calendar 类则会根据系统的日历来解释 Date 对象。下面详细介绍这两个类的具体使用。
Date 类
Date 类表示系统特定的时间戳,可以精确到毫秒。Date 对象表示时间的默认顺序是星期、月、日、小时、分、秒、年。
1. 构造方法
Date 类构造方法。
- Date():此种形式表示分配 Date 对象并初始化此对象,以表示分配它的时间(精确到毫秒),使用该构造方法创建的对象可以获取本地的当前时间。
使用示例如下:
Date date1 = new Date(); // 调用无参数构造函数
Date 类的无参数构造方法获取的是系统当前的时间,显示的顺序为星期、月、日、小时、分、秒、年。
- 常用方法
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 对象,其日历字段已由当前日期和时间初始化。
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:星期几。
例如,要获取当前月份可用如下代码:
int month = Calendar.getInstance().get(Calendar.MONTH);
如果整型变量 month 的值是 0,表示当前日历是在 1 月份;如果值是 11,则表示当前日历在 12 月份。
使用 Calendar 类处理日期时间的实例如下:
Calendar calendar = Calendar.getInstance(); // 如果不设置时间,则默认为当前时间calendar.setTime(new Date()); // 将系统当前时间赋值给 Calendar 对象System.out.println("现在时刻:" + calendar.getTime()); // 获取当前时间int year = calendar.get(Calendar.YEAR); // 获取当前年份System.out.println("现在是" + year + "年");int month = calendar.get(Calendar.MONTH) + 1; // 获取当前月份(月份从 0 开始,所以加 1)System.out.print(month + "月");int day = calendar.get(Calendar.DATE); // 获取日System.out.print(day + "日");int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; // 获取今天星期几(以星期日为第一天)System.out.print("星期" + week);int hour = calendar.get(Calendar.HOUR_OF_DAY); // 获取当前小时数(24 小时制)System.out.print(hour + "时");int minute = calendar.get(Calendar.MINUTE); // 获取当前分钟System.out.print(minute + "分");int second = calendar.get(Calendar.SECOND); // 获取当前秒数System.out.print(second + "秒");int millisecond = calendar.get(Calendar.MILLISECOND); // 获取毫秒数System.out.print(millisecond + "毫秒");int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); // 获取今天是本月第几天System.out.println("今天是本月的第 " + dayOfMonth + " 天");int dayOfWeekInMonth = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH); // 获取今天是本月第几周System.out.println("今天是本月第 " + dayOfWeekInMonth + " 周");int many = calendar.get(Calendar.DAY_OF_YEAR); // 获取今天是今年第几天System.out.println("今天是今年第 " + many + " 天");Calendar c = Calendar.getInstance();c.set(2012, 8, 8); // 设置年月日,时分秒将默认采用当前值System.out.println("设置日期为 2012-8-8 后的时间:" + c.getTime()); // 输出时间
上面的示例代码演示了 Calendar 类中的方法与常量的结合使用,从而完成处理日期的操作。
Java日期格式化(DateFormat类和SimpleDateFormat类)
在 Java 中,可以使用 DateFormat 类和 SimpleDateFormat 类来格式化日期,下面详细介绍这两个格式化日期类的使用。
DateFormat 类
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期→文本)、解析(文本→日期)和标准化日期。
在创建 DateFormat 对象时不能使用 new 关键字,而应该使用 DateFormat 类中的静态方法 getDateInstance(),示例代码如下:
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 类格式化曰期/时间的示例如下:
// 获取不同格式化风格和中国环境的日期DateFormat df1 = DateFormat.getDateInstance(DateFormat.SHORT, Locale.CHINA);DateFormat df2 = DateFormat.getDateInstance(DateFormat.FULL, Locale.CHINA);DateFormat df3 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.CHINA);DateFormat df4 = DateFormat.getDateInstance(DateFormat.LONG, Locale.CHINA);// 获取不同格式化风格和中国环境的时间DateFormat df5 = DateFormat.getTimeInstance(DateFormat.SHORT, Locale.CHINA);DateFormat df6 = DateFormat.getTimeInstance(DateFormat.FULL, Locale.CHINA);DateFormat df7 = DateFormat.getTimeInstance(DateFormat.MEDIUM, Locale.CHINA);DateFormat df8 = DateFormat.getTimeInstance(DateFormat.LONG, Locale.CHINA);// 将不同格式化风格的日期格式化为日期字符串String date1 = df1.format(new Date());String date2 = df2.format(new Date());String date3 = df3.format(new Date());String date4 = df4.format(new Date());// 将不同格式化风格的时间格式化为时间字符串String time1 = df5.format(new Date());String time2 = df6.format(new Date());String time3 = df7.format(new Date());String time4 = df8.format(new Date());// 输出日期System.out.println("SHORT:" + date1 + " " + time1);System.out.println("FULL:" + date2 + " " + time2);System.out.println("MEDIUM:" + date3 + " " + time3);System.out.println("LONG:" + date4 + " " + time4);
运行该段代码,输出的结果如下:
SHORT:18-10-15 上午9:30FULL:2018年10月15日 星期一 上午09时30分43秒 CSTMEDIUM:2018-10-15 9:30:43LONG:2018年10月15日 上午09时30分43秒
该示例主要介绍了 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 秒”,具体的实现代码如下:
import java.text.SimpleDateFormat;import java.util.Date;public class Test13 {public static void main(String[] args) {Date now = new Date(); // 创建一个Date对象,获取当前时间// 指定格式化格式SimpleDateFormat f = new SimpleDateFormat("今天是 " + "yyyy 年 MM 月 dd 日 E HH 点 mm 分 ss 秒");System.out.println(f.format(now)); // 将当前时间袼式化为指定的格式//Date d2 = format.parse("2022-03-16 23:44:24");}}
该程序的运行结果如下:
今天是 2018 年 10 月 15 日 星期一 09 点 26 分 23 秒
Java数字格式化(DecimalFormat)
DecimalFormat 是 NumberFormat 的一个子类,用于格式化十进制数字。DecimalFormat 类包含一个模式和一组符号,常用符号的说明如表 1 所示。
| 符号 | 说明 |
|---|---|
| 0 | 显示数字,如果位数不够则补 0 |
| # | 显示数字,如果位数不够不发生变化 |
例 1
下面编写一个 Java 程序,演示如何使用 DecimalFormat 类将数字转换成各种格式,实现代码如下。
//.后面的0,不够补0DecimalFormat format1 = new DecimalFormat("0.000");//,###:三个一组分割//.#后面不够不补充,DecimalFormat format2 = new DecimalFormat(",###.###");double d = 11232321100.6;System.out.println(format1.format(d));System.out.println(format2.format(d));
Java String 类
字符串是 Java 中特殊的类,使用方法像一般的基本数据类型,被广泛应用在 Java 编程中。Java 没有内置的字符串类型,而是在标准 Java 类库中提供了一个 String 类来创建和操作字符串。
在 Java 中定义一个字符串最简单的方法是用双引号把它包围起来。这种用双引号括起来的一串字符实际上都是 String 对象,如字符串“Hello”在编译后即成为 String 对象。因此也可以通过创建 String 类的实例来定义字符串。
不论使用哪种形式创建字符串,字符串对象一旦被创建,其值是不能改变的,但可以使用其他变量重新赋值的方式进行更改。
直接定义字符串
直接定义字符串是指使用双引号表示字符串中的内容,例如“Hello Java”、“Java 编程”等。具体方法是用字符串常量直接初始化一个 String 对象,示例如下:
String str = "Hello Java";
或者
String str;str = "Hello Java";
注意:字符串变量必须经过初始化才能使用。
例 1
下面的实例演示了直接创建字符串的几种用法。
String str = "我是一只小小鸟"; // 结果:我是一只小小鸟String word = "I am a bird"; // 结果:I am a birdword = "Let\'s say that it\'s true"; // 结果:Let's say that it's trueSystem.out.println(word);word = "北京\\上海\\广州"; // 结果:北京\上海\广州
使用 String 类定义
前面我们提到在 Java 中每个双引号定义的字符串都是一个 String 类的对象。因此,可以通过使用 String 类的构造方法来创建字符串,该类位于 java.lang 包中。
String 类的构造方法有多种重载形式,每种形式都可以定义字符串。下面介绍最常用的几种形式。
1. String()
初始化一个新创建的 String 对象,表示一个空字符序列。
2. String(String original)
初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列。换句话说,新创建的字符串是该参数字符串的副本。例如:
String str1 = new String("Hello Java");String str2 = new String(str1);
3. String(char[ ]value)
分配一个新的字符串,将参数中的字符数组元素全部变为字符串。该字符数组的内容已被复制,后续对字符数组的修改不会影响新创建的字符串。例如:
char a[] = {'H','e','l','l','0'};String sChar = new String(a);a[1] = 's';
上述 sChar 变量的值是字符串“Hello”。 即使在创建字符串之后,对 a 数组中的第 2 个元素进行了修改,但未影响 sChar 的值。
4. String中常用的方法
length()
字符串的长度
String a = "Hello Word!";System.out.println(a.length);//输出的结果是字符串长度10。
charAt()
截取一个字符
String a = "Hello Word";System.out.println(a.charAt(1));//输出的结果是字符串a的下标为1的字符e。
getBytes()
将字符串变成一个byte数组
String a = "Hello Word";byte b[] = a.getBytes();System.out.println(new String(b));//输出的结果为Hello Word的byte数组。
toCharArray()
将字符串变成一个字符数组
String a = "Hello Word";char[]b = a.toCharArray();System.out.println(b);//输出的结果为Hello Word字符数组。
equals()和equalsIgnoreCase():常用的
比较两个字符串是否相等,前者区分大小写,后者不区分
String a = "Hello Word";String b = "hello word";System.out.println(a.equals(b));System.out.println(a.equalsIgnoreCase(b));//输出的结果为第一条为false,第二条为true。
startsWith()和endsWith()
判断字符串是不是以特定的字符开头或结束
String a = "Hello Word";System.out.println(a.startsWith("ee"));System.out.println(a.endsWith("rd"));//输出的结果第一条为false,第二条为true。
toUpperCase()和toLowerCase()
将字符串转换为大写或小写
String a = "Hello Word";System.out.println(a.toUpperCase());System.out.println(a.toLowerCase());
输出的结果第一条为“HELLO WORD”,第二条为“hello word”。
trim()
去掉起始和结束的空格
String a = " Hello Word ";System.out.println(a.trim());//输出的结果为“Hello Word”。
substring()
截取字符串
String a = "Hello Word";System.out.println(a.substring(0, 5));System.out.println(a.substring(6));//输出的结果第一条为“Hello”,第一个参数0(beginIndex)//是开始截取的位置,第二个参数5(endIndex)是截取结束的位置//输出的结果第二条是“Word”,参数6(beginIndex)是开始截取的位置。
indexOf()和lastIndexOf()
前者是查找字符或字符串第一次出现的地方,后者是查找字符或字符串最后一次出现的地方
String a = "Hello Word";System.out.println(a.indexOf("o"));System.out.println(a.lastIndexOf("o"));//输出的结果第一条是4,是o第一次出现的下标,第二条是7,是o最后一次出现的下标。
replace()
替换
String a = "Hello Word";String b = "你好";System.out.println(a.replace(a, b));System.out.println(a.replace(a, "HELLO WORD"));System.out.println(b.replace("你", "大家"));//输出的结果第一条为“你好”,第二条为“HELLO WORD”,第三条为“大家好”。
split()
字符串分割
String name = "张三";System.out.println(name.split("")[0]);//张System.out.println(name.split("")[1]);//三String info = "我,热,爱Java编程";String[] infos = info.split(",");//[我,热,爱Java编程]for (String s : infos) {System.out.println(s);}
Java String:字符串常量池
作为最基础的引用数据类型,Java 设计者为 String 提供了字符串常量池以提高其性能,那么字符串常量池的具体原理是什么?
代码:从字符串常量池中获取相应的字符串
String str1 = "hello";//将字符串存储到常量池中String str2 = "hello";//拿到的是上面的helloSystem.out.println("str1 == str2 -> " + (str1 == str2) ); //trueString str3 = new String("hello");//新创建对象,存储在堆中Systme.out.println(str1 == str3);//false

StringBuffer和StringBuilder
StringBuffer
StringBuffer称为字符串缓冲区,它的工作原理是:预先申请一块内存,存放字符序列,如果字符序列满了,会重新改变缓存区的大小,以容纳更多的字符序列。StringBuffer是可变对象,这个是String最大的不同
public class StringBufferTest01 {public static void main(String[] args) {StringBuffer sbStr = new StringBuffer();for (int i=0; i<100; i++) {//sbStr.append(i);//sbStr.append(",");//方法链的编程风格sbStr.append(i).append(",");//拼串去除逗号//sbStr.append(i);//if (i != 99) {// sbStr.append(",");//}}//可以输出System.out.println(sbStr);System.out.println("");System.out.println(sbStr.toString());System.out.println("");//去除逗号System.out.println(sbStr.toString().substring(0,sbStr.toString().length()-1));System.out.println("");System.out.println(sbStr.substring(0, sbStr.length()-1));}}
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字符串匹配
//public boolean matches(String regex):判断是否与正则表达式匹配,匹配返回true// 只能是 a b cSystem.out.println("a".matches("[abc]")); // trueSystem.out.println("z".matches("[abc]")); // false// 不能出现a b cSystem.out.println("a".matches("[^abc]")); // falseSystem.out.println("z".matches("[^abc]")); // trueSystem.out.println("a".matches("\\d")); // falseSystem.out.println("3".matches("\\d")); // trueSystem.out.println("333".matches("\\d")); // falseSystem.out.println("z".matches("\\w")); // trueSystem.out.println("2".matches("\\w")); // trueSystem.out.println("21".matches("\\w")); // falseSystem.out.println("你".matches("\\w")); //falseSystem.out.println("你".matches("\\W")); // trueSystem.out.println("---------------------------------");//以上正则匹配只能校验单个字符。// 校验密码// 必须是数字 字母 下划线 至少 6位System.out.println("2442fsfsf".matches("\\w{6,}"));System.out.println("244f".matches("\\w{6,}"));// 验证码 必须是数字和字符 必须是4位System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));System.out.println("23_F".matches("[a-zA-Z0-9]{4}"));System.out.println("23dF".matches("[\\w&&[^_]]{4}"));System.out.println("23_F".matches("[\\w&&[^_]]{4}"));System.out.print("请输入密码:");Scanner scanner = new Scanner(System.in);String password = scanner.next();if(password.matches("\\w{2,10}")){System.err.println("密码符合规范");}else{System.err.println("密码不符合规范");}
二、String的replace、split
正则表达式在方法中的应用。
public String[] split(String regex):
— 按照正则表达式匹配的内容进行分割字符串,反回一个字符串数组。
public String replaceAll(String regex,String newStr)
— 按照正则表达式匹配的内容进行替换
String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";String[] arrs = names.split("\\w+");for (int i = 0; i < arrs.length; i++) {System.out.println(arrs[i]);}String names2 = names.replaceAll("\\w+", " ");System.out.println(names2);//将数字都给删除String str = "fdsfds3432432fdsfds564654dfsgfd564654";str = str.replaceAll("\\d+","");System.out.println(str);
三、匹配提取
java.util.regex 包主要包括以下三个类:
- Pattern 类:pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。
- Matcher 类:Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。
- PatternSyntaxException:PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。
以下实例中使用了正则表达式 .abc. 用于查找字符串中是否包了 abc 子串:
public static void main(String[] args){String content = "I am abc from abcdef.com.";String pattern = ".*abcdef.*";boolean isMatch = Pattern.matches(pattern, content);System.out.println("字符串中是否包含了 'abcdef' 子字符串? " + isMatch);}
String rs = "你好,我的邮箱是12sdfds3456@qq.com,fdsfa@432fds.mm手机号是17312341234";// 需求:从上面的内容中爬取出 电话号码和邮箱。// 1、定义爬取规则,字符串形式String regex = "(\\w{0,20}@\\w{0,6}\\.\\w{2,6})|(\\d{11})";// 2、把这个爬取规则编译成匹配对象。Pattern pattern = Pattern.compile(regex);// 3、得到一个内容匹配器对象Matcher matcher = pattern.matcher(rs);// 4、开始找了while (matcher.find()) {String rs1 = matcher.group();System.out.println(rs1);}
四、匹配规则
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/regex/Pattern.html
字符类[abc] a, b, 或c(简单类)[^abc] a除, b, 或c(否定)以外的任何字符[a-zA-Z] a通过z 或A通过Z,包括(范围)[a-d[m-p]] a通过d,或m通过p:([a-dm-p]联合)[a-z&&[def]] d, e, or f(intersection)[a-z&&[^bc]] a通过z,除了b和c:([ad-z]减法)[a-z&&[^m-p]] a通过z,而不是m通过p:([a-lq-z]减法预定义的字符类. 任何字符(可能与行终止符匹配,也可能不匹配)\d 一个数字:[0-9]\D 非数字:[^0-9]\h 水平空白字符: [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]\H 非水平空白字符:[^\h]\s 空白字符:[ \t\n\x0B\f\r]\S 非空白字符:[^\s]\v 垂直空白字符:[\n\x0B\f\r\x85\u2028\u2029]\V 非垂直空白字符:[^\v]\w 一个字字符:[a-zA-Z_0-9]\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} | m 和 n 是非负整数,其中 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 | 匹配 x 或 y。例如,’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),m 和 l 是八进制数 (0-7) 时,匹配八进制转义码 nml。 |
| \un | 匹配 n,其中 n 是以四位十六进制数表示的 Unicode 字符。例如,\u00A9 匹配版权符号 (©)。 |
