JAVA编程讲义之Java常用类
Java提供了强大的基础类库,可以简化开发,提高开发效率。这些类根据功能不同被划分到不同的包中,用户程序需要将其使用import关键字导入方可使用。本章将针对java.lang包、java.time包以及java.util包中的一些常用类进行讲解,包含字符串类、日期类、系统类、包装类以及数学相关类。
5
6
7
8
9
9.1 String类
在前面的内容中经常见到String类,使用它来定义一个字符串。所谓字符串,就是0个或多个字符组成的文本,必须使用""引起来定义,比如"AAA软件教育"。String类归到java.lang包中,lang包中的类无需导入,因此String类可直接使用。本节将讲解关于String类的基本操作。
9.1.1 String类初始化
在使用String类进行字符串操作之前,首先需要进行初始化。Java中对String类的初始有两种方式,具体如下:
• 直接给变量赋字符串常量值。使用字符串常量直接赋值给一个String对象,具体语法格式下:
String 变量名 = "字符串内容"。
• 使用构造方法进行初始化。String类的构造方法有多个,常用的构造如表9.1所示。
表9.1 String类常用构造方法
构造方法 |
方法描述 |
String() |
创建一个空的字符串对象,即字符串长度为0但不代表对象为null |
String(String original) |
根据一个字符串常量值来创建一个字符串对象 |
String(char value[]) |
将char数组中的元素拼接成一个字符串对象 |
String(char value[], int offset, int count) |
将一个char数组截取一定的范围转换成一个字符串对象,其中第一个参数是char数组,第二个参数是截取开始的下标,第三个参数为截取的位数 |
String(byte[] bytes) |
将一个byte数组转换成一个字符串对象 |
String(byte bytes[], int offset, int length) |
将一个byte数组截取一定的范围转换成一个字符串对象,其中第一个参数是byte数组,第二个参数是截取开始的下标,第三个参数为截取的位数 |
String(byte bytes[], int offset, int length, String charsetName) |
同上一个方法,区别在于上一个是按照平台默认编码格式进行转换,而这个是按照指定编码格式进行转换 |
接下来演示String类的多种构造方法的使用,如例9-1所示。
例9-1 Demo0901.java
1 package com.aaa.p0901;
2 public class Demo0901 {
3 public static void main(String[] args) {
4 String str = new String(); // 创建一个空的字符串
5 String str0 = new String("abcd"); // 创建一个字符串对象
6 System.out.println("根据字符串常量创建结果:"+str0);
7 char[] chars = {'a','b','c','d'};
8 String str1 = new String(chars); // 由字符数组创建一个字符串
9 System.out.println("char数组转换结果:" + str1);
10 String str2 = new String(chars,1,2); // 截取字符数组,转换成字符串
11 System.out.println("char数组从1开始转换2位的结果:" + str2);
12 byte[] bytes = {65,66,67,68};
13 String str3 = new String(bytes); // 由字节数组转换成字符串对象
14 System.out.println("byte数组转换结果:" + str3);
15 String str4 = new String(bytes,1,2); // 截取字节数组,转换成字符串
16 System.out.println("byte数组从1开始截取两位转换结果:" + str4);
17 }
18 }
程序的运行结果如下:
根据字符串常量创建结果:abcd
char数组转换结果:abcd
char数组从1开始转换2位的结果:bc
byte数组转换结果:ABCD
byte数组从1开始截取两位转换结果:BC
上述两种初始化形式创建的字符串效果是相同的,但是存储机制却存在很大的区别。
使用第一种“=”赋值常量的形式,JVM会去字符串常量池中查找是否存在"abcd"常量值,如果不存在,就在字符串常量池中开辟一个空间来存储;如果存在,则该变量直接指向"abcd"在字符串常量池中的地址值即可。并且,每一次变量值更改不会更改现在这个"abcd",而是重新在字符串常量池中查找,没有就重新开辟空间存储,因此字符串是不可变的,每次改变都是地址的重新开辟。
知识点拨:静态常量池是用来存储字符串常量值的一块内存空间。
接下来,我们可以声明两个变量存储相同的内容,输出“==”比对的结果来观察一下地址存储的情况,如例9-2所示。
例9-2 Demo0902.java
1 package com.aaa.p0901;
2 public class Demo0902 {
3 public static void main(String[] args) {
4 String str = "abcd";
5 String str1 = "abcd";
6 System.out.println(str==str1); // 结果为true
7 str1 = "abcde";
8 System.out.println(str==str1); // 结果为false
9 System.out.println("str的值:" + str);
10 System.out.println("str1的值:" + str1);
11 }
12 }
程序的运行结果如下:
true
false
str的值:abcd
str1的值:abcde
例9-2中,str和str1使用“==”比较的结果为true,说明两者存储地址是相同的,str1并没有重新开辟一个空间存储"abcd"而是直接指向了之前str开辟过的地址,即str和str1指向了相同的地址,内存显示如图9.1(a)。如果str1的值更改为"abcde",并不会更改现在这个地址的里的内容,而是重新查找是否含有"abcde",如果有指向,如果没有,重新开辟一个空间存储,然后指向新的地址。内存显示如图9.1(b)。
(a)str和str1指向相同的地址 (b)断开原来的地址链接指向新的地址
图9.1 str和str1的地址变化
注意:使用“==”关系运算符比较基本数据类型,可以用来判断值是否相同;比较的是引用数据类型,判断的是引用地址是否相同。
使用第二种形式,即new关键字调用构造方法,则每次初始化字符串对象都会在堆区开辟一个新的空间,因此使用new创建字符串对象无论内容是否一致,都会开辟不同的空间来存储。
接下来,我们可以使用new创建两个内容一致的字符串对象,输出“==”比对的结果来观察一下地址存储的情况,如例9-3所示。
例9-3 Demo0903.java
1 package com.aaa.p0901;
2 public class Demo0903 {
3 public static void main(String[] args) {
4 String str = new String("abcd");
5 String str1 = new String("abcd");
6 System.out.println("str==str1结果为:" + (str==str1));// 结果为false
7 }
8 }
程序的运行结果如下:
str==str1结果为:false
例9-3中,str和str1字符串的内容相同,“==”对比的结果为false,说明两者指向的地址是不同的,即使用new进行对象创建,每次都会开辟一个新的空间。
想一想:new String("abcd")创建了几个对象?
new String("abcd")必须在堆区中会创建一个对象,同时会查找字符串常量池中是否有“abcd”常量值,如果有那么不在创建,如果没有会创建一个,因此至少一个对象。
9.1.2 String类的常用方法
对于已经声明并且初始化的字符串,可以对其进行拼接、截取、判断长度等操作。本节将详细介绍常用的一些方法。包括:字符串比较、连接字符串、字符串查找、提取字符串、替换字符串、分割字符串等。其他大家可以下去查看API进行了解。
1.字符串判断比较
在Java程序开发中,字符串判断比较是最常见的问题。通过前文的学习,我们已经知道使用“==”可以比较两个字符串的地址是否相同,但是实际开发过程中所涉及到的字符串判断比较,并不都是简单的地址对比,有时候需要进行更全面、复杂的判断比较。为此,Java提供了丰富的字符串判断比较方法,最常用的如表9.2所示。
表9.2 字符串判断比较方法
方法 |
方法描述 |
int compareTo(String anotherString) |
按字符的ASCII码值对字符串进行大小比较,返回整数值。若当前对象比参数大则返回正整数,反之则返回负整数,相等则返回0。比较时先比较第一个字符,如果一样再比较第二个,以此类推 |
int compareToIgnore(String anotherString) |
与compareTo方法相似,但忽略大小写 |
boolean equals(Object anotherObject) |
该方法用来比较当前字符串和参数字符串中存储的内容是否一致,一致时返回true,否则返回false。与之前介绍的“==”不同,“==”比较的是地址,而equals比较的是地址中存储的值 |
boolean equalsIgnoreCase(String anotherString) |
与equals方法相似,但忽略大小写 |
boolean startsWith(String prefix) |
测试当前字符串是否以指定参数开头 |
boolean endsWith(String suffix) |
测试当前字符串是否以指定参数结尾 |
boolean isEmpty() |
判断字符串是否为空,即字符串的长度如果为0则返回true否则返回false |
boolean contains(CharSequence s) |
判断当前字符串中是否包含参数子串 |
接下来演示字符串的判断比较方法,如例9-4所示。
例9-4 Demo0904.java
1 package com.aaa.p0901;
2 public class Demo0904 {
3 public static void main(String[] args) {
4 String str = new String("AAA");
5 String str1 = new String("AAA");
6 String str2 = new String("aaa");
7 System.out.println("str==str1结果:"+(str==str1)); // ==比对地址
8 System.out.println("str.equals(str1)结果:"+str.equals(str1));// equals比对值
9 System.out.println("str.equals(str2)结果:"+str.equals(str2));
10 boolean result1=str.equalsIgnoreCase(str2);
11 System.out.println("str.equalsIgnoreCase(str2)结果:"+result1);
12 System.out.println("str.compareTo(str1)结果:"+str.compareTo(str1));
13 System.out.println("str.compareTo(str2)结果:"+str.compareTo(str2));
14 int result2=str.compareToIgnoreCase(str2);
15 System.out.println("str.compareToIgnoreCase(str2)结果:"+result2);
16 String str3 = "AAA软件教育14年!";
17 System.out.println("str3.startsWith(\"A\")结果:" + str3.startsWith("A"));
18 System.out.println("str3.endsWith(\"!\")结果:" + str3.endsWith("!"));
19 System.out.println("str3.contains(\"a\")结果:" + str3.contains("a"));
20 String str4="";
21 // 如果长度为0则返回true
22 System.out.println("str4.isEmpty()结果为:"+str4.isEmpty());
23 }
24 }
程序的运行结果如下:
str==str1结果:false
str.equals(str1)结果:true
str.equals(str2)结果:false
str.equalsIgnoreCase(str2)结果:true
str.compareTo(str1)结果:0
str.compareTo(str2)结果:-32
str.compareToIgnoreCase(str2)结果:0
str3.startsWith("A")结果:true
str3.endsWith("!")结果:true
str3.contains("a")结果:false
str4.isEmpty()结果为:true
例9-4中,str和str1是使用new初始化的两个存储内容都为"AAA "的字符串对象,内容相同地址不同,所以“==”比较地址返回的是false,equals比较存储内容,返回的是true。str存储的是"AAA "而str2存储的是"aaa ",大小写不同,所以equals对比结果为false,而equalsIgnoreCase忽略大小写对比返回的是true。str和str1存储内容完全一致,因为compareTo返回值为0。str和str2的大小写不同对比结果非0,结果-32的由来是因为"A "的ASCII值为65而"a"的ASCII值为97,两数之差是-32。CompareToIgnoreCase忽略大小写比较,因此"AAA "和"aaa "对比结果为0。最后22行,str4对象必须非null否则会出现空指针异常,该方法底层是调用length()方法,如果长度为0则返回true否则返回false。
误区警告:使用“==”对比的是地址,“new”方式初始化的字符串,里边的内容即便相同返回的也是false,因此在不能明确初始化方式是“=”赋值常量的情况下,不建议使用“==”来判断字符串是否相同,而要用“equals”方法来比较存储的内容是否一致。
2.字符串连接
字符串连接指的是将多个字符串拼接组成一个字符串。Java中提供两种方式进行字符串拼接:
• “+”拼接:使用“+”可以实现多个字符串连接形成一个新的字符串对象,并且如果“+”连接的是一个字符串和一个其他数据类型,返回的结果是字符串。
• String concat(String str)方法:将参数中的字符串str连接到当前字符串的后面,效果等价于使用“+”。
接下来演示字符串的拼接,如例9-5所示。
例9-5 Demo0905.java
1 package com.aaa.p0901;
2 public class Demo0905 {
3 public static void main(String[] args) {
4 String str1 = "AAA";
5 String str2 = "软件";
6 String str = str1 + str2 + "教育"; // "+"拼接字符串
7 System.out.println("str1+str2+\"教育\":" + str);
8 String str4 = str + 10 + 4 + "年";
9 System.out.println("str+10+4+\"年\":" + str4);
10 String str5 = 10 + 4 + "年"; // 字符串数字混合运算,从左往右运行
11 System.out.println("10+4+\"年\":" + str5);
12 String str6 = str + ( 10 + 4 ) + "年"; // ()提高优先级,先计算()再和字符串拼接
13 System.out.println("str+(10+4)+\"年\":" + str6);
14 str6 += "!"; // "+="复合赋值运算符,同于str6 = str6 + "!"
15 System.out.println("str6+=\"!\":" + str6);
16 String str7 = str1.concat(str2).concat("教育").concat("14年!");
17 System.out.println("concat拼接:" + str7); // 相当于str1+str2+"教育"+"14年!"
18 }
19 }
程序的运行结果如下:
str1+str2+"教育":AAA软件教育
str+10+4+"年":AAA软件教育104年
10+4+"年":14年
str+(10+4)+"年":AAA软件教育14年
str6+="!":AAA软件教育14年!
concat拼接:AAA软件教育14年!
例9-5中,“10+4+ "年"”的拼接结果为“14年”,即两个数字在前那么结果是先数字运算,在和字符串拼接;“"AAA软件教育"+10+4+"年"”拼接结果为“AAA软件教育104年”,说明如果数字在字符串后面,那么直接和字符串拼接,不会进行数学运算,但可以通过添加()使中间的数字先进行数学运算,在进行字符串拼接。
注意:String对象是不可变的,因此每次“+”拼接的结果都会在字符串常量池中产生新的字符串常量,如果需要频繁的字符串拼接,不建议使用String类,空间浪费;如果是字符串和数字的混合运算,从左往右依次运算,从碰到字符串的位置开始按照字符串拼接走。
3.提取字符串基本信息
字符串作为一个对象,可以通过该对象提供的特有方法,来获取字符串的一些基本信息,比如字符串长度、指定位置的字符等。具体方法如表9.3所示。
表9.3 提取字符串基本信息的方法
方法 |
方法描述 |
int length() |
返回字符串长度,即char的个数 |
char charAt(int index) |
获取索引位置的字符,index是索引下标,如果下标超出长度,会报错,其中索引从0开始 |
接下来演示提取字符串的方法,如例9-6所示。
例9-6 Demo0906.java
1 package com.aaa.p0901;
2 public class Demo0906 {
3 public static void main(String[] args) {
4 String str = "AAA软件教育14年";
5 int length = str.length();
6 System.out.println("length():" + length);
7 char ch = str.charAt(3);
8 System.out.println("charAt(3):" + ch);
9 char ch2 = str.charAt(10);
10 System.out.println("charAt(10):" + ch2);
11 }
12 }
程序的运行结果如下:
length():10
charAt(3):软
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: index 10, length 10
at java.base/java.lang.String.checkIndex(String.java:3693)
at java.base/java.lang.StringUTF16.checkIndex(StringUTF16.java:1584)
at java.base/java.lang.StringUTF16.charAt(StringUTF16.java:1381)
at java.base/java.lang.String.charAt(String.java:714)
at com.aaa.p0901.Demo0906.main(Demo0906.java:9)
例9-6中,length取值为字符的个数,与中英文无关;charAt(index)获取指定位置的字符,超出索引会报错。
4.提取子串
提取子串从本质上来说就是截取字符串的意思,即从一个特定的字符串中截取一定长度的子串。String类中提供了两个截取字符串的方法,一个是从指定位置开始,截取到该字符串的尾部;另一个是在指定范围内进行截取。具体方法如表9.4所示。
表9.4 提取子串的方法
方法 |
方法描述 |
String substring(int beginIndex) |
beginIndex位置起,从当前字符串中取出剩余的字符作为一个新的字符串返回 |
String substring(int beginIndex, int endIndex) |
beginIndex位置起到endIndex位置停,从当前字符串中取出该范围的字符作为一个新的字符串返回。子串中包含beginIndex不包含endIndex位置的内容 |
接下来演示提取子串即截取字符串的方法,如例9-7所示。
例9-7 Demo0907.java
1 package com.aaa.p0901;
2 public class Demo0907 {
3 public static void main(String[] args) {
4 String str = "AAA软件教育14年";
5 String sub1 = str.substring(1); // 从下标1开始截取,截取到尾部
6 System.out.println("substring(1):" + sub1);
7 String sub2 = str.substring(1,3); // 从下标1开始截取,截取到下标3(不包含3)
8 System.out.println("substring(1,3):" + sub2);
9 }
10 }
程序的运行结果如下:
substring(1):AA软件教育14年
substring(1,3):AA
例9-7中,第一个运行结果可以看出,从指定位置开始截取到了字符串的最后;第二个运行结果可以看出,截取的字符串包含开始位置不包含结束位置。需要注意的是,字符串的下标是从0开始的。
5.字符串的字符查找
在日常开发中,经常会用到需要判断字符串中是否包含另外一个字符串(子串)或者某个字符的情况。String类提供了indexOf()和lastIndexOf()方法来查找某个特定字符或者字符串(子串)在另一个字符串中出现的位置,具体方法如表9.5所示。
表9.5 字符串的字符查找方法
方法 |
方法描述 |
int indexOf(int ch/String str) |
该方法用于返回参数字符或者字符串在当前字符串中首次出现的索引位置。调用该方法,会从字符串的开始位置开始检索字符或者字符串,如果没有检索到返回-1,检索到返回首次找到的索引。其中“int ch”代表的是字符的ASCII码值,“String str”是一个子串 |
int indexOf(int ch/String str, int fromIndex) |
该方法与上一个类似,区别在于它不是从头开始检索,而是从指定位置fromIndex处开始查找 |
int lastIndexOf(int ch/String str) |
返回参数str或者ch字符在字符串中最右边出现的索引,即从右侧开始查找第一次出现的位置 |
int lastIndexOf(int ch/String str, int fromIndex) |
返回指定参数str或者ch字符在字符串中最右侧出现的位置,从指定的索引fromIndex开始从右往左进行查找 |
接下来演示字符串的字符查找方法,如例9-8所示。
例9-8 Demo0908.java
1 Package com.aaa.p0901;
2 public class Demo0908 {
3 public static void main(String[] args) {
4 String str = "AAA软件教育14年,专注教育14年";
5 int sub1 = str.indexOf(49); // '1'的ASCII值为49
6 System.out.println("indexOf(49)结果为:" + sub1);
7 int sub11 = str.indexOf("1");
8 System.out.println("indexOf(\"1\")结果为:" + sub11);
9 int sub12 = str.indexOf("1",10);
10 System.out.println("indexOf(\"1\",10)结果为:" + sub12);
11 int sub13 = str.lastIndexOf("1");
12 System.out.println("lastIndexOf(\"1\")结果为:" + sub13);
13 int sub14 = str.lastIndexOf("1",14); // 从14往前找,倒着找第一次出现1的位置
14 System.out.println("lastIndexOf(\"1\",14)结果为:" + sub14);
15 }
16 }
程序的运行结果如下:
indexOf(49)结果为:7
indexOf("1")结果为:7
indexOf("1",10)结果为:15
lastIndexOf("1")结果为:15
lastIndexOf("1",14)结果为:7
例9-8中,返回的索引位置是从0开始计算的;查找的参数可以是字符串、单个字符,也可以是字符的ASCII码值;数字49是字符'1'的ASCII码值。
6.字符串替换
在日常开发中,经常会遇到需要将字符串中的一个或多个子串替换成其他的字符串的需求,比如新闻中的一些敏感词汇替换成“*”等。String类提供了replace()方法、replaceFirst()以及replaceAll()方法来实现字符串替换功能,具体方法如表9.6所示。
表9.6 字符串的替换方法
方法 |
方法描述 |
String replace(CharSequence target, CharSequence replacement) |
该方法可以实现将指定字符序列(target)替换成新的字符序列(replacement),并返回一个新的字符串。CharSequence是一个接口,代表一个字符序列,String、StringBuffer、StringBuilder都实现了这个接口 |
String replaceFirst(String regex, String replacement) |
该方法用来将第一个指定的字符串或者第一个匹配的子串(regex)替换成新的字符串(replacement),支持正则表达式 |
String replaceAll(String regex, String replacement) |
该方法用来将所有指定的字符串或者匹配的子串(regex)替换成新的字符串(replacement),支持正则表达式 |
接下来演示字符串的替换方法,如例9-9所示。
例9-9 Demo0909.java
1 package com.aaa.p0901;
2 public class Demo0909 {
3 public static void main(String[] args) {
4 String str = "AAA软件教育14年,专注教育14年";
5 String newStr = str.replace("14","十四"); // 将所有的14替换成十四
6 System.out.println("替换后的新字符串:" + newStr);
7 String newStr1 = str.replaceFirst("14","十四");
8 System.out.println("replaceFirst替换后的字符串:" + newStr1);
9 String newStr2 = str.replaceAll("14","十四"); // 将匹配的子串全部替换
10 System.out.println("replaceAll根据字符串替换结果:" + newStr2);
11 String newStr3 = str.replaceAll("1.","十四"); // 将匹配正则的内容全部替换
12 System.out.println("replaceAll根据正则表达式替换结果:" + newStr3);
13 System.out.println("替换前字符串:" + str); // 所有操作不影响原有对象
14 }
15 }
程序的运行结果如下:
替换后的新字符串:AAA软件教育十四年,专注教育十四年
replaceFirst替换后的字符串:AAA软件教育十四年,专注教育14年
replaceAll根据字符串替换结果:AAA软件教育十四年,专注教育十四年
replaceAll根据正则表达式替换结果:AAA软件教育十四年,专注教育十四年
替换前字符串:AAA软件教育14年,专注教育14年
例9-9中,所有的替换都没有影响原来的字符串,返回了一个新的字符串对象。
7.字符串中字符的大小写转换
String类提供了toLowerCase()方法用于将当前字符串中的所有字符转换成小写;同时,也提供了toUpperCase()方法用于将当前字符串中所有的字符转换成大写。
接下来演示字符串的大小写转换方法,如例9-10所示。
例9-10 Demo0910.java
1 package com.aaa.p0901;
2 public class Demo0910 {
3 public static void main(String[] args) {
4 String str = "AAA软件教育14年,专注教育14年";
5 String strLow = str.toLowerCase();
6 System.out.println("toLowerCase调用转换后:" + strLow);
7 String strUpper = strLow.toUpperCase();
8 System.out.println("toUpperCase调用转换后:" + strUpper);
9 }
10 }
程序的运行结果如下:
toLowerCase调用转换后:aaa软件教育14年,专注教育14年
toUpperCase调用转换后:AAA软件教育14年,专注教育14年
8.去除两端空格
在日常开发中我们可能会遇到需要将某个字符串两端的空格去除这样的问题,比如接收录入的参数中含有前后空格就需要将其去除。String类提供了trim()方法,用于截去字符串两端的空格,但对于中间的空格不处理。
接下来演示字符串的空格去除方法,如例9-11所示。
例9-11 Demo0911.java
1 package com.aaa.p0901;
1 public class Demo0911 {
2 public static void main(String[] args) {
3 String str = " AAA软件教育14年 专注教育14年 ";// 前一个空格,后一个空格,中间一个空格
4 System.out.println(str + "----的长度为:" + str.length());
5 String strTrim=str.trim();
6 System.out.println(strTrim + "----的长度为:" + strTrim.length());
7 }
8 }
程序的运行结果如下:
AAA软件教育14年 专注教育14年 ----的长度为:20
AAA软件教育14年 专注教育14年----的长度为:18
例9-11中,两次结果只差2个空格即前后两个,中间的空格还在。
9.分隔符进行字符串分解
String类提供了split(String str)方法,该方法可将参数str作为分隔符进行字符串分解,分解后返回的是一个字符串数组。
接下来演示字符串的分解方法,如例9-12所示。
例9-12 Demo0912.java
1 package com.aaa.p0901;
9 public class Demo0912 {
10 public static void main(String[] args) {
11 String str = "AAA软件,AAA品牌,AAA经历,AAA梦想";
12 String[] strs = str.split(",");
13 for(int i = 0;i < strs.length;i++){
14 System.out.println("第" + i + "个字符串是:" + strs[i]);
15 }
16 }
17 }
程序的运行结果如下:
第0个字符串是:AAA软件
第1个字符串是:AAA品牌
第2个字符串是:AAA经历
第3个字符串是:AAA梦想
以上是String类的一些常用的方法,由于字符串使用频繁,所以要多加练习熟练掌握,它还有很多其他的方法,读者可以查看API进行深入学习。
注意:String对象是不可变的,以上所有方法的操作都是返回的字符串对象而不影响原来的字符串对象。
9.2 StringBuffer类
StringBuffer类与String类一样都是用来存储字符串的,区别在于String类创建的字符串不可变,内容一经定义便不可更改,每次更改String对象的值都需要开辟新的空间,而StringBuffer对象的空间开辟后内容是可以改变的,且容量会随着存放的字符增加而自动增加。接下来,我们对StringBuffer类展开学习。
9.2.1 创建StringBuffer对象
创建一个新的StringBuffer对象,必须通过new的形式进行,不像String对象可以用new也可以直接用“=”赋值常量。StringBuffer类的常用构造方法如表9.7所示。
表9.7 StringBuffer类的构造方法
方法 |
方法描述 |
StringBuffer() |
创建一个没有初始值的字符串对象 |
StringBuffer(String str) |
创建一个带有初始值的字符串 |
StringBuffer(int capacity) |
创建一个定义了初始空间的空字符串 |
接下来演示StringBuffer对象的多种创建方式,如例9-13所示。
例9-13 Demo0913.java
1 package com.aaa.p0902;
2 public class Demo0913 {
3 public static void main(String[] args) {
4 StringBuffer str = new StringBuffer();
5 System.out.println("没有初始值的构造方法:" + str.length());
6 StringBuffer str2 = new StringBuffer("AAA");
7 System.out.println("带有初始值的构造方法:" + str2.length());
8 StringBuffer str3 = new StringBuffer(10);
9 System.out.println("初始容量为10,实际长度为:" + str3.length());
10 }
11 }
程序的运行结果如下:
没有初始值的构造方法:0
带有初始值的构造方法:3
初始容量为10,实际长度为:0
例9-13中,带有初始空间的字符串仅仅只是定义了初始空间,真实的字符串长度仍然是0。
9.2.2 StringBuffer类常用方法
StringBuffer类提供了多种方法,比如查找方法、替换方法、拆分方法等,这些方法在使用上与String类所提供的方法差别不大。除此之外,StringBuffer类还提供了一些特有方法,具体如表9.8所示。
表9.8 StringBuffer类的常用方法
方法 |
方法描述 |
StringBuffer append() |
在字符串尾部追加,该方法是一个重载的方法,里边接收参数有多种,int、字符串、字符、char数组、StringBuffer对象等都可以 |
StringBuffer insert(int offset,String str) |
在字符串的指定位置offset插入指定字符串str |
StringBuffer reverse() |
将字符串进行反转 |
StringBuffer delete(int start,int end) |
将字符串中指定范围的字符删除,范围从索引start开始到end-1的位置停。如果end-1超出了最大索引,那么直接删除到尾部;如果start等于end,那么不会删除任何字符;如果start大于end则会直接抛出异常 |
接下来演示StringBuffer类的常用方法的使用,如例9-14所示。
例9-14 Demo0914.java
1 package com.aaa.p0902;
2 public class Demo0914 {
3 public static void main(String[] args) {
4 StringBuffer str = new StringBuffer("AAA软件");
5 System.out.println("创建的str对象:" + str);
6 str.append("专业软件"); // 追加字符串
7 str.append(14); // 追加数字
8 str.append('年'); // 追加字符
9 System.out.println("追加后的结果:" + str);
10 System.out.println("-----------------------------");
11 str.insert(9,"已经");
12 System.out.println("insert插入后结果:" + str);
13 System.out.println("-----------------------------");
14 StringBuffer str2 = new StringBuffer("AAA软件");
15 str2.reverse();
16 System.out.println("AAA软件反转后结果:" + str2);
17 System.out.println("-----------------------------");
18 StringBuffer stringBuffer = new StringBuffer("0123456789");
19 stringBuffer.delete(4,8); // 删除内容含4不含8
20 System.out.println("delete(4,8):" + stringBuffer);
21 stringBuffer = new StringBuffer("0123456789");
22 stringBuffer.delete(4,10); // 10超出了最大的索引,直接删除到尾部
23 System.out.println("delete(4,10):" + stringBuffer);
24 }
25 }
程序的运行结果如下:
创建的str对象:AAA软件
追加后的结果:AAA软件专业软件14年
-----------------------------
insert插入后结果:AAA软件专业软件已经14年
-----------------------------
AAA软件反转后结果:件软AAA
-----------------------------
delete(4,8):012389
delete(4,10):0123
以上是StringBuffer类的常用方法,除此之外,还有很多和String类相似的方法,可以参考String类进行尝试,同时还有一些独有的方法,可以参考API进行学习。
想一想:String类和StringBuffer类的区别?什么时候适合使用String类,什么时候适合使用StringBuffer类?
知识点拨:Java中除了StringBuffer类可以处理可变字符串之外,它还有一个StringBuilder类。它是StringBuffer类的简化,使用基本一样,因此本章节不在重复介绍,它的速度快但线程安全性差。
9.3 日期时间类
在实际开发过程中,经常会用到日期、时间,同时还需要对日期、时间进行处理,Java提供了多个类来处理日期时间,本节就来详细讲解这些类。
9.3.1 Date类
Date类用来表示日期时间,位于java.util包中。
1.创建Date对象
Date类有很多构造方法,其中大部分都已经不推荐使用,表9.9列出了目前最常用的两种。
表9.9 Date类目前最常用的两种构造方法
方法 |
方法描述 |
Date() |
创建一个Date对象,并且初始值为系统当前日期 |
Date(long date) |
创建一个Date对象,参数为指定时间距标准基准时间的毫秒数 |
接下来演示Date类构造方法的使用,如例9-15所示。
例9-15 Demo0915.java
1 package com.aaa.p0903;
2 import java.util.Date;
3 public class Demo0915 {
4 public static void main(String[] args) {
5 Date date = new Date();
6 System.out.println(date);
7 long dateLong = System.currentTimeMillis();// 获取当前时间距标准基准时间的毫秒数
8 Date date2 = new Date(dateLong);
9 System.out.println(date2);
10 }
11 }
程序的运行结果如下:
Mon May 03 21:57:21 CST 2021
Mon May 03 21:57:21 CST 2021
例9-15中,两种方式都是创建了一个Date对象,其中第5行是使用无参构造方法创建Date对象,表示系统当前时间;第8行使用有参构造方法创建Date对象,中间的毫秒数指的是距离标准基准时间的毫秒数,这一行可以根据这个数值转换成Date日期格式。
注意:System.currentTimeMillis()方法用来获取系统当前时间距离标准基准时间(1970-01-01 00:00:00)的毫秒数。
2.Date类的常用方法
在实际开发中,使用日期的地方一般都会涉及日期的操作,比如日期的对比、获取年、获取月等。Date类提供了很多相关的方法,其中大部分已经被其他日期类及其相关方法所取代,目前还比较常用的方法如表9.10所示。
表9.10 Date类的常用方法
方法 |
方法描述 |
boolean after(Date when) |
判断当前日期对象是否在指定when日期之后 |
boolean before(Date when) |
判断当前日期对象是否在指定when日期之前 |
long getTime() |
获取自1970-01-01 00:00:00到当前日期对象的毫秒数 |
void setTime(long time) |
设置当前Date对象的日期值,参数为毫秒数 |
接下来演示Date类的常用方法,如例9-16所示。
例9-16 Demo0916.java
1 package com.aaa.p0903;
2 import java.text.ParseException;
3 import java.text.SimpleDateFormat;
4 import java.util.Date;
5 public class Demo0916 {
6 public static void main(String[] args) {
7 String birth1 = "1990-01-01";
8 String birth2 = "1990-02-01";
9 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
10 try {
11 Date birthDate1 = format.parse(birth1); // 字符串birth1转换成日期
12 Date birthDate2 = format.parse(birth2); // 字符串birth2转换成日期
13 boolean after = birthDate1.after(birthDate2);
14 boolean before = birthDate1.before(birthDate2);
15 // 1月1日在2月1日前边,因此为false
16 System.out.println("1.1 after 2.1比较结果为:" + after);
17 // 1月1日在2月1日前边,因此为true
18 System.out.println("1.1 before 2.1比较结果为:" + before);
19 System.out.println("获取所经历的毫秒值:" + birthDate1.getTime());
20 } catch (ParseException e) {
21 e.printStackTrace();
22 }
23 }
24 }
程序的运行结果如下:
1.1 after 2.1比较结果为:false
1.1 before 2.1比较结果为:true
获取所经历的毫秒值:631123200000
注意:Date类大部分方法都已经不再推荐使用,JDK8之后,使用最频繁的日期类是LocaDate类、LocalDateTime类,在后续章节将详细讲解。
9.3.2 Calendar类
Date类中获取年、获取月、根据指定年月日进行对象创建等方法都已经不推荐使用,这些过时的方法很多都被Calendar类及其相关方法替代。Calendar类也称日历类,同样位于java.util包中,可以指定年月日,可以获取年月日,也可以对日期进行加减运算。Calendar类是一个抽象类,不可以用new关键字来创建对象,需要通过getInstance()方法来获取实例,代表的是系统当前时间,也可以通过其子类GregorianCalendar类来创建对象。Calendar类提供的常用方法如表9.11所示。
表9.11 Calendar类的常用方法
方法 |
方法描述 |
Calendar getInstance() |
返回一个系统当前日期的日历对象 |
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_OF_DAY一天中的小时,MINUTE分钟,SECOND秒的值 |
void setTime(long time) |
将给定的日期字段field设置成指定值value |
void setTime(Date date) |
将Date类型日期值设置给Calendar对象 |
void setTimeInMillis (long millis) |
将给定的long毫秒数设置给Calendar对象 |
Date getTime() |
返回一个与之对应的Date对象 |
int get(int field) |
返回指定日历字段的值 |
void add(int field,int amount) |
根据日期规则,给指定的字段添加或者减去指定时间量 |
接下来演示Calendar日历类的常用方法,如例9-17所示。
例9-17 Demo0917.java
1 package com.aaa.p0903;
2 import java.util.Calendar;
3 public class Demo0917 {
4 public static void main(String[] args) {
5 Calendar date = Calendar.getInstance();
6 int year = date.get(Calendar.YEAR);
7 int month = date.get(Calendar.MONTH) + 1; // 注意:月份从0开始
8 int day = date.get(Calendar.DAY_OF_MONTH);
9 System.out.println("系统当前时间:" + year + "年" + month + "月" + day + "日");
10 Calendar date2 = Calendar.getInstance();
11 date2.set(2022,0,1,0,0,0); // 设置年月日时分秒,month0代表1月
12
13 long dlong1 = date.getTimeInMillis(); // 获取当前日期的毫秒值
14 long dlong2 = date2.getTimeInMillis(); // 获取2022-1-1的毫秒值
15 long daym = (dlong2-dlong1)/(24*60*60*1000); // 计算两个毫秒值之间的差并换算成天
16 System.out.println("距离2022年元旦还有:" + daym);
17 }
18 }
程序的运行结果如下:
系统当前时间:2021年5月3日
距离2022年元旦还有:242
9.3.3 LocalDate类和LocalTime类
JDK1.8中,新增了LocalDate类、LocalTime类、LocalDateTime类等几个日期时间类,位于java.time包中,都是不可变的。在日期时间的处理上,这些类提供了更丰富的方法以及更清晰的格式,逐渐替代了之前的Date类。
1.LocalDate类
LocalDate类用来表示日期,只有年月日,没有时分秒。LocalDate类不能通过new关键字来创建对象,它提供了两种获取对象的方法:一个是使用now()获取系统当前时间;另外一个是使用of(int year,int month,int dayOfMonth)根据指定年月日来创建日期对象。具体语法如下:
LocalDate 变量名 = LocalDate.now();
LocalDate 变量名 = LocalDate.of(年,月,日);
除now()和of()方法外,LocalDate类还提供了获取日期信息、日期运算、格式化的方法,常用方法具体如表9.12所示。
表9.12 LocalDate类的常用方法
方法 |
说 明 |
LocalDate now() |
获取当前日期 |
LocalDate of(int year, int month, int dayOfMonth) |
根据参数设置日期,参数分别为年,月,日 |
int getDayOfMonth() |
获取当前日期是所在月的第几天 |
DayOfWeek getDayOfWeek() |
获取当前日期所在星期,是一个DayOfWeek枚举类的值 |
int getDayOfYear( ) |
获取当前日期是所在年的第几天 |
Month getMonth() |
获取当前日期所在月份,是一个Month枚举类的值 |
int getMonthValue() |
获取当前日期所在月份的数值 |
int lengthOfMonth() |
获取当前日期所在月份有多少天 |
int lengthOfYear() |
获取当前日期所在年有多少天 |
boolean isEqual(ChronoLocalDate other) |
判断两个日期是否相同 |
boolean isLeapYear() |
获取当前日期所在年是否是闰年 |
LocalDate withDayOfMonth(int dayOfMonth) |
指定当前月的第几天,返回一个新的日期,不影响当前 |
LocalDate withDayOfYear(int dayOfYear) |
指定当前年的第几天,返回一个新的日期,不影响当前 |
LocalDate withMonth(int month) |
指定月,返回一个新的日期,不影响当前 |
LocalDate withYear(int year) |
指定年,返回一个新的日期,不影响当前 |
LocalDate minusDays(long days) |
将当前日期减days天,返回一个新的日期,不影响当前 |
LocalDate minusWeeks(long weeks) |
将当前日期减weeks周,返回一个新的日期,不影响当前 |
LocalDate minusMonths(long months) |
将当前日期减months月,返回一个新的日期,不影响当前 |
LocalDate minusYears(long years) |
将当前日期减years年,返回一个新的日期,不影响当前 |
LocalDate plusDays(long days) |
将当前日期加days天,返回一个新的日期,不影响当前 |
LocalDate plusWeeks(long weeks) |
将当前日期加weeks周,返回一个新的日期,不影响当前 |
LocalDate plusMonths(long months) |
将当前日期加months月,返回一个新的日期,不影响当前 |
LocalDate plusYears(long years) |
将当前日期加years年,返回一个新的日期,不影响当前 |
接下来演示LocalDate类常用方法的使用,如例9-18所示。
例9-18 Demo0918.java
1 package com.aaa.p0903;
2 import java.time.LocalDate;
3 public class Demo0918 {
4 public static void main(String[] args) {
5 LocalDate date = LocalDate.now();
6 System.out.println("系统当前时间:" + date);
7 LocalDate ofDate = LocalDate.of(2021 , 12 , 12);
8 System.out.println("of获取的日期信息:" + ofDate);
9 // 该方法会返回一个新的日期对象,对原来的日期对象并不会更改
10 ofDate = ofDate.withDayOfMonth(30); // 参数是这个月的第30天
11 System.out.println("withDayOfMonth(30):" + ofDate);
12 ofDate = ofDate.withDayOfYear(30); // 参数是这一年的第30天
13 System.out.println("withDayOfYear(30):" + ofDate);
14 ofDate = ofDate.plusDays(30); // 加30天,不影响原来日期,返回一个新的日期
15 System.out.println("plusDays(30):" + ofDate);
16 System.out.println("getMonthValue:" + ofDate.getMonthValue());// 获取月份值
17 System.out.println("lengthOfMonth:" + ofDate.lengthOfMonth());// 获取一月天数
18 System.out.println("lengthOfYear:" + ofDate.lengthOfYear()); // 获取一年天数
19 System.out.println("两个日期是否相等:" + ofDate.isEqual(date));
20 }
21 }
程序的运行结果如下:
系统当前时间:2021-05-03
of获取的日期信息:2021-12-12
withDayOfMonth(30):2021-12-30
withDayOfYear(30):2021-01-30
plusDays(30):2021-03-01
getMonthValue:3
lengthOfMonth:31
lengthOfYear:365
两个日期是否相等:false
例9-18中,每次调用with、plus等日期操作时都需要重新赋值,因为LocalDate对象不可变,方法返回的都是一个新的对象。
2.LocalTime类
LocalTime类产生的对象是一个不可变的时间对象,以纳秒精度表示,此类只存储时分秒,而不存日期和时区。LocalTime类也不能通过new关键字来创建对象,它同样提供了两个获取对象的方法:一个是now()获取系统当前时间;另外一个是of()方法,这个是一个重载的方法,可以根据指定小时、分钟来获取对象,也可以根据指定小时、分钟、秒来获取对象,还可以根据指定小时、分钟、秒、纳秒来获取对象。具体语法如下:
LocalTime 变量名 = LocalTime.now();
LocalTime 变量名 = LocalTime.of(时,分,秒);
LocalTime 变量名 = LocalTime.of(时,分);
LocalTime 变量名 = LocalTime.of(时,分,秒,纳秒);
除now()和of()方法外,LocalTime类还提供了获取时间信息、进行时间运算、格式化的方法,常用方法与LocalDate类似,此处不在一一说明。
接下来演示LocalTime类常用方法的使用,如例9-19所示。
例9-19 Demo0919.java
1 package com.aaa.p0903;
2 import java.time.LocalTime;
3 public class Demo0919 {
4 public static void main(String[] args) {
5 LocalTime time = LocalTime.now();
6 System.out.println("系统当前时间:" + time);
7 LocalTime ofTime = LocalTime.of(12,12,12);
8 System.out.println("of获取的时间信息:" + ofTime);
9 ofTime = ofTime.withHour(20); // 设定小时为20,不改变原对象并返回一个新时间对象
10 System.out.println("ofTime.withHour(20):" + ofTime);
11 ofTime = ofTime.plusMinutes(60); // 加60分钟
12 System.out.println("ofTime.plusMinutes(60):" + ofTime);
13 int hours = ofTime.getHour(); // 获取小时
14 System.out.println("ofTime.getHour():" + hours);
15 }
16 }
程序的运行结果如下:
系统当前时间:22:09:51.569664
of获取的时间信息:12:12:12
ofTime.withHour(20):20:12:12
ofTime.plusMinutes(60):21:12:12
ofTime.getHour():21
以上案例中都没有对格式化进行讲解,会在后续章节中进行详细讲解。
9.3.4 LocalDateTime类
LocalDateTime类可以设置年月日时分秒,是LocalDate类和LocalTIme类的综合,可以通过now()和of()方法获取对象。它同时含有LocalDate类和LocalTime类的方法,而且还提供了额外的转换方法。
接下来演示LocalDateTime对象的获取以及常用方法的使用,如例9-20所示。
例9-20 Demo0920.java
1 package com.aaa.p0903;
2 import java.time.LocalDate;
3 import java.time.LocalDateTime;
4 import java.time.LocalTime;
5 public class Demo0920 {
6 public static void main(String[] args) {
7 LocalDateTime dateTime = LocalDateTime.now(); // 通过now()获取系统当前时间
8 System.out.println("系统当前时间:" + dateTime);
9 LocalDateTime ofD = LocalDateTime.of(2021,12,12,10,10,10); // 通过of获取对象
10 System.out.println("通过of(年,月,日,时,分,秒)创建的时间:" + ofD);
11 LocalDate date = LocalDate.of(2021,12,12);
12 LocalTime time = LocalTime.of(10,10,10);
13 // 通过LocalDate和LocalTime组合成LocalDateTime对象
14 LocalDateTime ofD1 = LocalDateTime.of(date,time);
15 System.out.println("LocalDate,LocalTime组合时间:" + ofD1);
16 ofD = ofD.withDayOfMonth(2); // 指定月
17 System.out.println("ofD.withDayOfMonth(2):" + ofD);
18 ofD = ofD.plusMonths(1); // 加一个月
19 System.out.println("ofD.plusMonths(1):" + ofD);
20 LocalDate localDate = ofD.toLocalDate(); // 获取LocalDate
21 System.out.println("ofD.toLocalDate():" + localDate);
22 // LocalDate加上LocalTime组成LocalDateTime
23 LocalDateTime dateTime1 = localDate.atTime(LocalTime.now());
24 System.out.println("localDate.atTime(LocalTime.now()):" + dateTime1);
25 }
26 }
程序的运行结果如下:
系统当前时间:2021-04-30T09:29:08.197235300
通过of(年,月,日,时,分,秒)创建的时间:2021-12-12T10:10:10
LocalDate,LocalTime组合时间:2021-12-12T10:10:10
ofD.withDayOfMonth(2):2021-12-02T10:10:10
ofD.plusMonths(1):2022-01-02T10:10:10
ofD.toLocalDate():2022-01-02
localDate.atTime(LocalTime.now()):2022-01-02T09:29:08.213225500
例9-20中,演示了LocalDateTime对象的多种获取形式和常用方法,基本操作与LocalDate对象和LocalTime对象一样。除此之外,还演示了几个类之间的转换,第14行是将LocalDate对象和LocalTime对象通过of()方法组合成LocalDateTIme对象,第23行是通过atTime()方法将两者组合成一个LocalDateTime对象,第20行是从LocalDateTIme对象中获取一个LocalDate对象。
9.3.5 日期时间格式化类
以上实例不难看出,程序中输出的日期根据所有日期类的不同显示结果也有所不同,并且都不太符合常规显示习惯。因此,需要引入日期时间格式化类,将日期时间转换成指定格式的字符串。例如,将日期“Fri Apr 23 20:50:51 CST 2021”格式转换为“2021-04-23 20:50:51 周五”。除此之外,实际开发项目中经常会录入“1990-01-05”这样的日期字符串,这些日期字符串没有办法进行日期比较以及一些日期运算,因此需要将其转换成日期时间格式进行操作。Java中提供了多种方式来实现这些功能,本节将针对常用的格式化日期类:DateFormate类、SimpleDateFormat类、DateTimeFormatter类进行详细讲解。
1. DateFormat类格式化
DateFormat类是一个抽象类,不能使用关键字new来创建对象,可以通过该类中提供的静态方法来获取一个实例对象,可以根据需要的格式选择不同的静态方法,但是不能自定义格式。该类提供了format()方法来实现将日期时间对象格式化成字符串,同时提供了parse()方法来实现将字符串解析成日期时间对象,具体方法说明如表9.13所示。
表9.13 DateFormat对象的获取方法以及常用方法
分类 |
方法 |
方法描述 |
对象的获取方法 |
static DateFormat getDateTimeInstance() |
获取具有默认格式化风格和默认语言环境的日期/时间格式 |
static DateFormat getDateTimeInstance(int dateStyle , int timeStyle,Locale locale) |
获取具有指定日期格式化风格、指定时间格式化风格和指定语言环境的。其中格式化风格有以下几种:SHORT:完全为数字;MEDIUM:较长;LONG:更长;FULL:完全指定 |
|
static DateFormat getInstance() |
获取日期时间格式化风格都使用SHORT风格的格式化器 |
|
格式化方法 |
String format(Date date) |
将日期根据指定格式格式化成字符串 |
Date parse(String source) |
将给定的字符串解析成日期/时间,如果字符串和格式不匹配,运行时会抛出ParseException异常 |
接下来演示DateFormat类对象的获取以及常用方法的使用,如例9-21所示。
例9-21 Demo0921.java
1 package com.aaa.p0903;
12 import java.text.DateFormat;
13 import java.text.ParseException;
14 import java.util.Date;
15 import java.util.Locale;
16 public class Demo0921 {
17 public static void main(String[] args) {
18 System.out.println("---------------日期格式化成指定格式的字符串---------");
19 Date date = new Date();
20 DateFormat f1 = DateFormat.getInstance(); // 期时间格式化风格都使用SHORT
21 System.out.println("SHORT风格:" + f1.format(date));
22 f1 = DateFormat.getDateTimeInstance(DateFormat.FULL , DateFormat.FULL ,
23 Locale.CHINA); // 指定风格和环境
24 System.out.println("FULL风格和中文环境:" + f1.format(date));
25 f1 = DateFormat.getDateTimeInstance(); // 默认风格 默认语言环境
26 System.out.println("默认风格 默认语言环境:" + f1.format(date));
27 System.out.println("---------------将字符串解析成日期对象------------");
28 String birth = "2019年10月26日 上午11:11:11";
29 try {
30 Date date1 = f1.parse(birth);
31 System.out.println("转换后的日期:" + date1);
32 } catch (ParseException e) {
33 e.printStackTrace();
34 }
35 }
36 }
程序的运行结果如下:
---------------日期格式化成指定格式的字符串---------
SHORT风格:2021/4/30 上午11:19
FULL风格和中文环境:2021年4月30日星期五 中国标准时间 上午11:19:39
默认风格 默认语言环境:2021年4月30日 上午11:19:39
---------------将字符串解析成日期对象------------
转换后的日期:Sat Oct 26 11:11:11 CST 2019
例9-21分为两部分,上半部分用来展示日期格式化成字符串,3个方法分别展示的是SHORT风格、FULL风格以及默认的MEDIUM风格的显示;后半部分展示的是字符串解析成日期,注意字符串的格式必须和声明的DateFormat对象格式一致,否则会出现异常。
2. SimpleDateFormat类格式化
SimpleDateFormat类是DateFormat类的子类,可以自定义格式。该类可以通过new关键字来创建对象,同样提供了format()方法与parse()方法进行日期和字符串之间转换,其常用方法如表9.14所示。
表9.14 SimpleDateFormat类常用的构造方法与成员方法
分类 |
方法 |
方法描述 |
构造方法 |
SimpleDateFormat(String pattern) |
指定日期格式创建一个SimpleDateFormat对象 |
SimpleDateFormat(String pattern,Local local) |
指定日期的格式和地区创建一个SimpleDateFormat对象,这个local参数对星期显示有关键作用 |
|
成员方法 |
String format(Date date) |
将日期根据指定格式格式化成字符串 |
Date parse(String source) |
将符合格式的字符串转换成日期,如果字符串和格式不匹配,运行时会抛出ParseException异常 |
接下来演示SimpleDateFormat类常用方法的使用,如例9-22所示。
例9-22 Demo0922.java
1 package com.aaa.p0903;
18 import java.text.ParseException;
19 import java.text.SimpleDateFormat;
20 import java.util.Date;
21 import java.util.Locale;
22 public class Demo0922 {
23 public static void main(String[] args) {
24 System.out.println("---------日期格式成字符串---------");
25 Date date = new Date();
26 System.out.println("没有格式化之前的日期:" + date);
27 SimpleDateFormat f1 ; // 定义地区为中国
28 f1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EE",Locale.CHINA);
29 String strDate = f1.format(date);
30 System.out.println("格式化之后:" + strDate);
31 SimpleDateFormat f2 ; // 定义地区为美国
32 f2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss EE",Locale.US);
33 String strDate1 = f2.format(date);
34 System.out.println("定义位置为美国来进行格式化:" + strDate1);
35 SimpleDateFormat f3 ;
36 f3 = new SimpleDateFormat("yyyy-MM-dd"); // 定义地区为默认
37 String strDate2 = f3.format(date);
38 System.out.println("只保留年月日格式化:" + strDate2);
39 System.out.println("-----------字符串解析成日期对象-----------");
40 String birth = "1990-10-10"; // 字符串需要和下边定义的格式一致,否则转换不成功
41 SimpleDateFormat f4 = new SimpleDateFormat("yyyy-MM-dd");
42 try {
43 Date birthDate = f4.parse(birth);
44 System.out.println("字符串转换成日期:" + birthDate);
45 } catch (ParseException e) {
46 e.printStackTrace();
47 }
48 }
49 }
程序的运行结果如下:
---------日期格式成字符串---------
没有格式化之前的日期:Fri Apr 30 11:47:05 CST 2021
格式化之后:2021-04-30 11:47:05 周五
定义位置为美国来进行格式化:2021-04-30 11:47:05 Fri
只保留年月日格式化:2021-04-30
-----------字符串解析成日期对象-----------
字符串转换成日期:Wed Oct 10 00:00:00 CST 1990
例9-22中,第12行按照中国习惯进行格式化声明,第16行按照美国习惯进行格式化声明,对比二者格式化结果可以发现,在星期方面差距很大。
注意:格式规则中yyyy代表年,MM代表月,dd代表日,HH代表小时(24小时制),hh代表小时(12小时制),mm代表分钟,ss代表秒,E代表星期,S毫秒,D一年中的第几天, w一年中的第几个星期,W一月中的第几星期,a上下午标识。
3.DateTimeFormatter类格式化
Java8新增的日期时间API,除了前边讲解的LocalDate类、LocalTime类、LocalDateTime类以外,还包括用于日期时间格式化的DateTimeFormatter类。它与SimpleDateFormat类的区别在于:DateTimeFormatter类是线程安全的而SimpleDateFormat类是线程不安全的;DateTimeFormatter类可以格式化LocalDate、LocalDateTime、LocalTIme对象而SimpleDateFormat类一般用来格式化Date对象。
DateTimeFormatter类提供了ofPattern(String pattern)方法进行格式化设置,参数pattern的定义规则是:yyyy代表年、MM代表月、dd代表日、HH代表24小时制的小时、hh代表12小时制的小时、mm代表分钟、ss代表秒。这个类格式化日期有两种形式:
• 使用DateTimeFormatter类的format()方法。
• 使用LocalDate类、LocalDateTime类、LocalTime类的format()方法。
接下来演示使用DateTimeFormatter类分别将LocalDateTime类型、LocalDate类型、LocalTime类型的对象格式化成字符串,如例9-23所示。
例9-23 Demo0923.java
1 package com.aaa.p0903;
2 import java.time.LocalDate;
3 import java.time.LocalDateTime;
4 import java.time.LocalTime;
5 import java.time.format.DateTimeFormatter;
6 public class Demo0923 {
7 public static void main(String[] args) {
8 LocalDateTime dateTime = LocalDateTime.now();
9 System.out.println("LocalDateTime原始格式:" + dateTime);
10 // 定义一个格式为“年-月-日 时:分:秒”
11 DateTimeFormatter f1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
12 // 定义一个格式为“年-月-日"
13 DateTimeFormatter f2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
14 // 定义一个格式为"时:分:秒"
15 DateTimeFormatter f3 = DateTimeFormatter.ofPattern("HH:mm:ss");
16 System.out.println("-----------LocalDateTime的format()方法格式化------");
17 String dateStr = dateTime.format(f1); // LocalDateTime的format方法
18 System.out.println("yyyy-MM-dd HH:mm:ss格式化后:" + dateStr);
19 dateStr = dateTime.format(f2);
20 System.out.println("yyyy-MM-dd格式化后:" + dateStr);
21 System.out.println("-DateTimeFormatter的format()方法格式化LocalDateTime-");
22 dateStr = f1.format(dateTime); // DateTimeFormatter的format方法
23 System.out.println("yyyy-MM-dd HH:mm:ss格式化后:" + dateStr);
24 dateStr = f2.format(dateTime);
25 System.out.println("yyyy-MM-dd格式化后:" + dateStr);
26
27 LocalDate localDate = LocalDate.now();
28 System.out.println("LocalDate原始格式:" + localDate);
29 System.out.println("-----------LocalDate的format()方法格式化-------");
30 dateStr = localDate.format(f2); // LocalDate的格式中只能有年月日
31 System.out.println("yyyy-MM-dd格式化后:" + dateStr);
32 System.out.println("---DateTimeFormatter的format()方法格式化LocalDate---");
33 dateStr = f2.format(localDate); // DateTimeFormatter的format方法
34 System.out.println("yyyy-MM-dd格式化后:" + dateStr);
35
36 LocalTime localTime = LocalTime.now();
37 System.out.println("LocalTime原始格式:" + localTime);
38 System.out.println("------------LocalTime的format()方法格式化-------");
39 dateStr = localTime.format(f3); // LocalTime的格式中不能有年月日
40 System.out.println("HH:mm:ss格式化后:" + dateStr);
41 System.out.println("---DateTimeFormatter的format()方法格式化LocalTime---");
42 dateStr = f3.format(localTime); // DateTimeFormatter的format方法
43 System.out.println("HH:mm:ss格式化后:" + dateStr);
44 }
45 }
程序的运行结果如下:
LocalDateTime原始格式:2021-04-30T14:39:04.869342200
------------LocalDateTime的format()方法格式化-------
yyyy-MM-dd HH:mm:ss格式化后:2021-04-30 14:39:04
yyyy-MM-dd格式化后:2021-04-30
------------DateTimeFormatter的format()方法格式化LocalDateTime-------
yyyy-MM-dd HH:mm:ss格式化后:2021-04-30 14:39:04
yyyy-MM-dd格式化后:2021-04-30
LocalDate原始格式:2021-04-30
------------LocalDate的format()方法格式化-------
yyyy-MM-dd格式化后:2021-04-30
------------DateTimeFormatter的format()方法格式化LocalDate-------
yyyy-MM-dd格式化后:2021-04-30
LocalTime原始格式:14:39:04.884332700
------------LocalTime的format()方法格式化-------
HH:mm:ss格式化后:14:39:04
------------DateTimeFormatter的format()方法格式化LocalTime-------
HH:mm:ss格式化后:14:39:04
需要特别强调的是,LocalDate、LocalTime、LocalDateTime 3种对象格式化成字符串用的都是DateTimeFormatter类,但是定义格式要求不同。其中,LocalDateTime对象可以使用年月日时分秒,LocalDate对象中只能有年月日,LocalTime对象中不能有年月日。
4.DateTimeFormatter类解析字符串
DateTimeFormatter类可以将日期格式化成字符串,也可以将字符串解析成日期对象,有如下两种形式可以实现:
• 使用LocalDate、LocalDateTime、LocalTime类的parse(CharSequence text, DateTimeFormatter formatter)方法。
• 使用DateTimeFormatter类的parse()方法配合相关日期时间类的from()方法,该方式相对于第一种方式而言比较麻烦。
接下来演示使用DateTimeFormatter将字符串格式化成3种类型的日期对象,如例9-24所示。
例9-24 Demo0924.java
1 package com.aaa.p0903;
2 import java.time.LocalDate;
3 import java.time.LocalDateTime;
4 import java.time.LocalTime;
5 import java.time.format.DateTimeFormatter;
6 import java.time.temporal.TemporalAccessor;
7 public class Demo0924 {
8 public static void main(String[] args) {
9 DateTimeFormatter f1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
10 DateTimeFormatter f2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
11 DateTimeFormatter f3 = DateTimeFormatter.ofPattern("HH:mm:ss");
12 System.out.println("------LocalDateTime类的parse()方法解析字符串--------");
13 String dateStr = "2011-01-01 12:12:12";
14 LocalDateTime dateTime = LocalDateTime.parse(dateStr,f1);
15 System.out.println("LocalDateTime日期格式:" + dateTime);
16 System.out.println("-----DateTimeFormatter类的parse()方法解析字符串---------");
17 TemporalAccessor dateTime1= f1.parse(dateStr);
18 dateTime = LocalDateTime.from(dateTime1);
19 System.out.println("LocalDateTime日期格式:" + dateTime);
20 System.out.println("---------LocalDate类的parse()方法解析字符串-----------");
21 dateStr="2011-01-11";
22 LocalDate date=LocalDate.parse(dateStr,f2);
23 System.out.println("LocalDate日期格式:" + date);
24 System.out.println("---------LocalTime类的parse()方法解析字符串-----------");
25 String timeStr = "11:11:11";
26 LocalTime time = LocalTime.parse(timeStr,f3);
27 System.out.println("LocalTime日期格式:" + time);
28 }
29 }
程序的运行结果如下:
---------LocalDateTime类的parse()方法解析字符串-----------
LocalDateTime日期格式:2011-01-01T12:12:12
---------DateTimeFormatter类的parse()方法解析字符串-----------
LocalDateTime日期格式:2011-01-01T12:12:12
---------LocalDate类的parse()方法解析字符串-----------
LocalDate日期格式:2011-01-11
---------LocalTime类的parse()方法解析字符串-----------
LocalTime日期格式:11:11:11
例9-24中,被解析的字符串格式需和DateTimeFormatter对象创建时设置的参数格式保持一致,否则会抛出DateTimeParseException异常。
9.4 系统相关类
9.4.1 System类
System类对于大家来说其实并不陌生,向控制台打印信息的System.out.println()方法就是System类提供的。System类位于java.lang包中,没有构造方法,提供了大量的静态方法,可以获取与系统相关的信息以及系统级操作。本节将介绍该类的常用方法。
1.currentTimeMillis()方法
currentTimeMillis()方法的声明语句是static long currentTimeMillis(),该方法用于获取当前系统时间,返回的是毫秒值,表示系统当前时间距离标准基准时间(1970-01-01 00:00:00)的毫秒数。这个方法在之前章节已经使用过,此处不再介绍。
2.arraycopy()方法
arraycopy()方法的声明语句是static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length),该方法可将数组中指定的数据拷贝到另一个数组中。其中,src为源数据,srcPos为源数据中的开始位置,dest为目标数组,destPos为目标数据中的开始位置,length为要复制的数组元素的数量。
接下来演示arraycopy()方法的使用,如例9-25所示。
例9-25 Demo0925.java
1 package com.aaa.p0904;
37 import java.util.Arrays;
38 public class Demo0925 {
39 public static void main(String[] args) {
40 int[] src = new int[]{11,22,33,44,55,66};// 源数组
41 int[] dest = new int[]{111,222,333,444}; // 目的数组
42 System.out.println("源数组:" + Arrays.toString(src));
43 System.out.println("目的数组拷贝前内容:" + Arrays.toString(dest));
44 System.arraycopy(src, 2, dest, 1, 2); // 调用arraycopy()方法
45 System.out.println("目的数组拷贝后内容:" + Arrays.toString(dest));
46 }
47 }
程序的运行结果如下:
源数组:[11, 22, 33, 44, 55, 66]
目的数组拷贝前内容:[111, 222, 333, 444]
目的数组拷贝后内容:[111, 33, 44, 444]
例9-25中,从结果可以看出arraycopy()方法从源数组拷贝,放到目标数组中,会覆盖目标数组中原来位置的内容,并不是插入。
3.gc()方法
gc()方法的声明语句是static void gc(),该方法用来建议JVM赶快启动垃圾回收器。只是建议启动,JVM是否启动又是另外一回事。
接下来演示gc()方法的使用,如例9-26所示。
例9-26 Demo0926.java
1 package com.aaa.p0904;
2 class Student {
3 String name;
4 public Student(String name) {
5 this.name = name;
6 }
7 @Override
8 protected void finalize() throws Throwable {
9 super.finalize();
10 System.out.println(name + "被回收了");
11 }
12 }
13 public class Demo0926 {
14 public static void main(String[] args) {
15 for(int i = 1;i <= 8;i++){
16 new Student("对象" + i);
17 System.gc();
18 }
19 }
20 }
程序的运行结果如下:
对象1被回收了
对象8被回收了
对象7被回收了
对象6被回收了
对象5被回收了
对象4被回收了
对象3被回收了
对象2被回收了
例9-26中,通过循环语句多次调用gc()方法是因为它仅仅是建议回收,不一定能触发垃圾回收机制,因此多调用几次加大触发的概率。
注意:finalize()方法是Object的一个方法,此处Student类将其重写,这个方法会在垃圾回收时被调用。
4.getProperty()方法
getProperty ()方法的声明语句是static String getProperty (String key),该方法用于根据系统的属性名获取对应的属性值。
接下来演示getProperty ()方法的使用,如例9-27所示。
例9-27 Demo0927.java
1 package com.aaa.p0904;
48 public class Demo0927 {
49 public static void main(String[] args) {
50 String osName = System.getProperty("os.name");
51 System.out.println("操作系统的类型:"+osName);
52 String javaHome = System.getProperty("java.home");
53 System.out.println("JDK的根路径:" + javaHome);
54 String pathStr = System.getProperty("java.vm.version");
55 System.out.println("JVM虚拟机版本:" + pathStr);
56 }
57 }
程序的运行结果如下:
操作系统的类型:Windows 10
JDK的根路径:C:\Program Files\Java\jdk-15.0.2
JVM虚拟机版本:15.0.2+7-27
例9-27中,JDK的路径和安装路径有关,如果安装路径更改这个路径输出会与本书不一致。 这个案例只输出了3个属性值,实际有很多,大家根据需要可以更改属性名来获取不同的属性值。
5.exit()方法
exit()方法的声明语句是static void exit(int status),该方法用于退出JVM,如果参数为0表示正常退出,非0表示异常退出。退出JVM后,后面的代码将不在执行。无论参数传0还是传1,JVM都会退出。
9.4.2 Runtime类
Runtime类封装了运行时的环境。每个Java应用程序都有一个Runtime类实例,使应用程序能够与运行的环境相连接。不能实例化一个Runtime对象,这个类是一个单例,可以通过getRuntime 方法获取当前Runtime运行时对象的引用。一旦得到当前的Runtime对象引用,就可以调用Runtime对象的方法去控制Java虚拟机的状态和行为。
Runtime的功能主要有:查看系统内存、终止JVM虚拟机、运行系统程序等。其常用方法如表9.15所示。
表9.15 Runtime类的常用方法
方法 |
方法描述 |
Runtime getRuntime() |
用于获取Runtime实例。 |
long freeMemory() |
用于返回Java虚拟机的空闲内存量。 |
long maxMemory() |
用于返回Java虚拟机试图使用的最大内存量。 |
long totalMemory() |
用于返回Java虚拟机的内存总量。 |
void exec(String command) |
用于根据指定的路径执行对应的可执行文件。 |
接下来演示Runtime类常用方法的使用,如例9-28所示。
例9-28 Demo0928.java
1 package com.aaa.p0904;
2 import java.io.IOException;
3 public class Demo0928 {
4 public static void main(String[] args) {
5 Runtime runtime = Runtime.getRuntime(); // 获取Runtime实例
6 System.out.println("虚拟机中的空闲内存量:" + runtime.freeMemory());
7 System.out.println("虚拟机试图使用的最大内存量:" + runtime.maxMemory());
8 System.out.println("虚拟机中的内存总量:" + runtime.totalMemory());
9 try {
10 runtime.exec("calc"); // 运行指定可执行文件
11 } catch (IOException e) {
12 e.printStackTrace();
13 }
14 }
15 }
程序的运行结果如图9.2所示。
图9.2 例9-28运行结果
9.5 包装类
Java中8大基本数据类型不能直接视为对象操作,无法赋值为null,也不能用在泛型中,如果字符串想转换成数字也无法直接通过强转达到。即基本数据类型简化了开发但是在开发中很多地方都有所不足,为了解决这些不足,Java提供了包装类,主要作用是将基本数据类型封装在包装类中。
包装类就是基本数据类型和对象之间的一个桥梁,可以进行相互转换。将基本数据类型转换为对象的过程即是装箱,将对象转换为基本数据类型的过程即是拆箱,JDK1.5中,提供了自动拆装箱,即基本数据类型和其封装类可以自动转换。Java中基本数据类型的包装类如表9.16所示。
表9.16 基本数据类型包装类
基本数据类型 |
包装类 |
基本数据类型 |
包装类 |
byte |
Byte |
Float |
Float |
short |
Short |
Double |
Double |
int |
Integer |
Char |
Character |
long |
Long |
Boolean |
Boolean |
9.5.1 数值型包装类
八种基本数据类型中:有4个整型,它们的包装类分别为Byte类、Short类、Integer类、Long类;两个浮点型,包装类分别为Double类、Float类。这些类都是Number类的子类,包含的方法和使用方式都基本一致,因此在此只介绍Integer类,其他数值类型的包装类大家可以参考学习。Integer对象的获取有多种方式,具体如表9.17所示。
表9.17 Integer对象的获取方法
方法 |
方法描述 |
new Integer(int value) |
构造方法,以int型为参数创建一个Integer对象 |
new Integer(String s) |
构造方法,以String字符串为参数创建一个Integer对象,这个字符串必须包含的是数字,否则会出现NumberFormatException异常 |
static Integer valueOf(String s) |
把该String字符串转化成Integer对象,如果String中存储的不是数字会出现异常 |
Static Integer valueOf(int i) |
把int类型包装成一个Integer对象 |
static Integer getInteger(String nm) |
根据指定的名称得到系统属性的整数值。第一个参数将被认为是系统属性的名称,没有将返回null |
直接赋值数字的常量值 |
使用自动装箱进行对象获取 |
表9.17所示的Integer对象的获取方法的具体实例如下:
Integer int1 = new Integer(11111);
Integer int2 = new Integer(“11111”); // 不推荐
Integer int3 = 11111; // 使用自动装箱进行对象获取
Integer int4 = Integer.valueOf(11111);
Integer int5 = Integer.valueOf(“11111”);
如表9.18所示,列出了Integer类的常用方法。
表9.18 Integer类的常用方法
方法 |
方法描述 |
static int parseInt(String s) |
将字符串转换成int类型 |
static String toBinaryString(int i) |
将数字转换成二进制进行显示 |
static String toHexString(int i) |
将数字转换成十六进制进行显示 |
static String toOctalString(int i) |
将数字转换成八进制进行显示 |
boolean equals(Object obj) |
比较对象中存储的内容是否相等 |
int intValue() |
以int型返回该对象的值 |
byte byteValue() |
以byte型返回该对象的值 |
short shortValue() |
以short型返回该对象的值 |
接下来演示Integer类常用方法的使用,如例9-29所示。
例9-29 Demo0929.java
1 package com.aaa.p0905;
2 public class Demo0929 {
3 public static void main(String[] args) {
4 int i = Integer.parseInt(“123”); // 字符串转换成数字
5 String two = Integer.toBinaryString(111);
6 System.out.println(“二进制:” + two);
7 String six = Integer.toHexString(111);
8 System.out.println(“十六进制:” + six);
9 String eight = Integer.toOctalString(111);
10 System.out.println(“八进制:” + eight);
11 Integer inte = new Integer(111);
12 Integer inte1 = new Integer(111);
13 System.out.println(“inte==inte1:” + (inte==inte1)); // 比对地址
14 System.out.println(“inte.equals(inte1):” + inte.equals(inte1)); // 比对内容
15 }
16 }
程序的运行结果如下:
二进制:1101111
十六进制:6f
八进制:157
inte==inte1:false
inte.equals(inte1):true
例9-28中,使用Integer声明的整数是引用数据类型;使用“==”比对的是地址,因为new关键字的形式创建对象每次都会开辟新的空间,因此比对结果返回的是false;而equals()方法对比的是存储内容,因此比对结果返回的是true。
除了表9.18列出的常用方法以外,Integer类还提供了以下几个常量:
• MAX_VALUE:表示int类型可取最大值,为2的31次方减1。
• MIN_VULUE:表示int类型可取的最小值,为-2的31次方。
• SIZE:表示用来以二进制补码形式表示int值的位数。
其他数值型的相关封装类与Integer类似,在此不再一一说明。
9.5.2 Boolean类
Boolean类是boolean类型的包装类,提供了将boolean类型包装成一个对象的方法、String类型和boolean类型转换的方法,以及一些其他常用方法和常量。Boolean对象的获取有多种方式,具体如表9.19所示。
表9.19 Boolean对象的获取方式
方法 |
方法描述 |
new Boolean(Boolean value) |
构造方法,以boolean型为参数创建一个Boolean对象 |
new Boolean(String s) |
构造方法,以String字符串为参数创建一个Boolean对象,这个字符串必须”true”才是true否则都是false |
Static Boolean valueOf(String s) |
把该String字符串转化成Boolean对象 |
static Boolean valueOf(boolean b) |
把boolean类型包装成一个Boolean对象 |
直接赋值boolean类型的常量值 |
使用自动装箱进行对象获取 |
表9.19所示的Boolean对象的获取方法的具体实例如下:
Boolean b1 = new Boolean(true);
Boolean b2 = new Boolean(“true”);
Boolean b3 = Boolean.valueOf(“true”);
Boolean b4 = true;
如表9.20所示,列出了Boolean类的常用方法。
表9.20 Boolean类的常用方法
方法 |
方法描述 |
static boolean parseBoolean(String s) |
将字符串转换成boolean类型,这个字符串必须”true”才是true否则都是false |
boolean equals(Object obj) |
比较对象中存储的内容是否相等 |
boolean booleanValue() |
以boolean型返回该对象的值 |
接下来演示Boolean类常用方法的使用,如例9-30所示。
例9-30 Demo0930.java
1 package com.aaa.p0905;
2 public class Demo0930 {
3 public static void main(String[] args) {
4 // 将字符串转换成boolean类型,必须”true”才是true否则都是false
5 boolean b3 = Boolean.parseBoolean(“true”);
6 Boolean b1 = new Boolean(true);
7 Boolean b2 = new Boolean(“true”);
8 System.out.println(“b1.booleanValue():” + b1.booleanValue());
9 System.out.println(“b1==b2:” + (b1==b2));
10 System.out.println(“b1.equals(b2):” + (b1.equals(b2)));
11 }
12 }
程序的运行结果如下:
b1.booleanValue():true
b1==b2:false
b1.equals(b2):true
9.5.3 Character类
Character类是char类型的包装类,该类提供了很多方法可以实现字符和数字转换、字符大小写之间的转换。Character对象的获取有多种方式,具体如表9.21所示。
表9.21 Character对象的获取方式
方法 |
方法描述 |
new Character (char value) |
构造方法,以char型为参数创建一个Character对象 |
static Character valueOf(char c) |
把该char值转化成Character对象 |
直接赋值char类型的常量值 |
使用自动装箱进行对象获取 |
表9.21所示的Character对象的获取方法的具体实例如下::
Character char1 = new Character(‘c’);
Character char2 = ’C’;
Character char3 = Character.valueOf(‘c’);
如表9.22所示,列出了Character类的常用方法。
表9.22 Character类的常用方法
方法 |
方法描述 |
boolean equals(Object obj) |
比较对象中存储的内容是否相等 |
static boolean isLetter(char c) |
用于判断指定字符是否为字母 |
static boolean isDigit(char c) |
用于判断指定字符是否为数字 |
static boolean isUpperCase(char c) |
用于判断指定字符是否为大写字母 |
static boolean isLowerCase (char c) |
用于判断指定字符是否为小写字母 |
static char toUpperCase (char c) |
用于将小写字符转换为大写 |
static char toLowerCase (char c) |
用于将大写字符转换为小写 |
接下来演示Character类常用方法的使用,如例9-31所示。
例9-31 Demo0931.java
1 package com.aaa.p0905;
50 public class Demo0931 {
51 public static void main(String[] args) {
52 System.out.println(“isUpperCase(‘c’):” + Character.isUpperCase(‘c’));
53 System.out.println(“isLowerCase(‘c’):” + Character.isLowerCase(‘c’));
54 System.out.println(“isLetter(‘c’):” + Character.isLetter(‘c’));
55 System.out.println(“isDigit(‘c’):” + Character.isDigit(‘c’));
56 System.out.println(“toUpperCase(‘c’):” + Character.toUpperCase(‘c’));
57 }
58 }
程序的运行结果如下:
isUpperCase(‘c’):false
isLowerCase(‘c’):true
isLetter(‘c’):true
isDigit(‘c’):false
toUpperCase(‘c’):C
9.6 数学相关类
Java语言提供了丰富的数字处理类,包括Math类、BigInteger类、Random类以及数字格式化类。本节将对这些类做详细讲解。
9.6.1 Math类
Math类的作用是进行一些数学运算,位于java.lang包中。该类包含了许多用于执行基本数学运算的常量以及函数方法。
Math类中的常量主要有PI(圆周率)、E(自然对数底数)等;方法主要有取整数、绝对值、最大值、最小值、对数、平方根和三角函数等。Math类的方法都是以static的形式定义的,因此这些方法可以在主函数中直接调用(Math.数学方法)。
Math类中常用的数学运算方法如表9.23所示。
表9.23 Math常用方法
方法 |
方法描述 |
static int abs(int a) |
该方法用于计算参数的绝对值,参数可以是整形、(int)长整型(long)、浮点型(float)、双精度型(double) |
static double ceil(double a) |
该方法用于计算>=给定参数的最小整数 |
static double floor(double a) |
该方法用于计算<=给定参数的最小整数 |
static double rint(double a) |
该方法用于计算与参数最接近的整数,返回double类型 |
static int round(float a) |
该方法用于计算参数四舍五入后的结果 |
static int min(int a, int b) |
该方法用于计算两个参数中的最小值,参数可以是整形(int)、长整型(long)、浮点型(float)、双精度型(double) |
static int max(int a, int b) |
该方法用于计算两个参数中的最大值 |
static double random() |
该方法用于生成一个随机数 |
static double pow(double a, double b) |
该方法用于计算指数函数的值 |
static double sqrt(double a) |
该方法用于计算参数开平方的结果 |
接下来演示Math类常用方法的使用,如例9-32所示。
例9-32 Demo0932.java
1 package com.aaa.p0906;
2 public class Demo0932 {
3 public static void main(String[] args) {
4 System.out.println("-----------------常量部分-----------");
5 System.out.println("圆周率PI:" + Math.PI);
6 System.out.println("自然对数底数E:" + Math.E);
7 System.out.println("-----------------常用方法-----------");
8 System.out.println("-20绝对值:" + Math.abs(-20));
9 System.out.println(">=6.01的最小整数:" + Math.ceil(6.01));
10 System.out.println("<=6.01的最小整数:" + Math.floor(6.01));
11 // rint获取的是最近的整数,如果两个整数一样近,返回偶数哪一个。
12 System.out.println("6.5最接近的整数:" + Math.rint(6.5));
13 System.out.println("6.5四舍五入后的结果:" + Math.round(6.5));
14 System.out.println("最小值:" + Math.min(6,8));
15 System.out.println("最大值:" + Math.max(6,8));
16 // 生成大于等于0小于1的随机数,类型是double
17 System.out.println("随机数:" + Math.random());
18 System.out.println("3的2次方:" + Math.pow(3,2));
19 System.out.println("4的平方根:" + Math.sqrt(4));
20 }
21 }
程序的运行结果如下:
-----------------常量部分-----------
圆周率PI:3.141592653589793
自然对数底数E:2.718281828459045
-----------------常用方法-----------
-20绝对值:20
>=6.01的最小整数:7.0
<=6.01的最小整数:6.0
6.5最接近的整数:6.0
6.5四舍五入后的结果:7
最小值:6
最大值:8
随机数:0.13786516645597535
3的2次方:9.0
4的平方根:2.0
9.6.2 BigInteger类
在Java语言中,提供了用于进行大数字运算的BigInteger类,该类位于java.math包中,被称为大整数类。BigInteger类型的数字范围要比Integer类型的数字范围大得多,并且支持任意精度的整数。
要使用BigInteger类,首先需要创建一个BigInteger对象。BigInteger类提供了多种构造方法,其中最常用的是接收String类型参数的构造方法,具体语法如下:
BigInteger bigInteger = new BigInteger("5000000000");
BigInteger类是一个引用数据类型,因此,常规的运算符号(+、-、*、/)是不能使用的,可以通过该对象中相应的封装方法来进行操作。除了这些基础运算之外,该类还提供有求绝对值、相反数、最大公约数等数学运算方法。
BigInteger类中常用的数学运算方法如表9.24所示。
表9.24 BigInteger常用方法
方法 |
方法描述 |
BigInteger add(BigInteger val) |
加法运算 |
BigInteger subtract(BigInteger val) |
减法运算 |
BigInteger multiply(BigInteger val) |
乘法运算 |
BigInteger divide(BigInteger val) |
除法运算 |
BigInteger remainder(BigInteger val) |
取余数运算 |
BigInteger[] divideAndRemainder(BigInteger val) |
除法运算,返回数组的第一个值为商,第二个值为余数 |
BigInteger pow(int exponent) |
做参数的 exponent 次方运算 |
BigInteger negate() |
取相反数 |
BigInteger min(BigInteger val) |
返回较小的数值 |
BigInteger max(BigInteger val) |
返回较大的数值 |
接下来演示BigInteger类常用方法的使用,如例9-33所示。
例9-33 Demo0933.java
1 package com.aaa.p0906;
2 import java.math.BigInteger;
3 import java.util.Scanner;
4 public class Demo0933 {
5 public static void main(String[] args) {
6 BigInteger bigA = new BigInteger("100000");
7 BigInteger bigB = new BigInteger("200000");
8 System.out.println("A+B的值:" + bigA.add(bigB));
9 System.out.println("A-B的值:" + bigA.subtract(bigB));
10 System.out.println("A×B的值:" + bigA.multiply(bigB));
11 System.out.println("A÷B的值:" + bigA.divide(bigB));
12 System.out.println("取余数:" + bigA.remainder(bigB));
13 System.out.println("A÷B的值(返回数组):"
14 + "--商:" + bigA.divideAndRemainder(bigB)[0]
15 + "--余数:" + bigA.divideAndRemainder(bigB)[1]);
16 System.out.println("A取相反数:" + bigA.negate());
17 System.out.println("A、B比较返回小值:" + bigA.min(bigB));
18 System.out.println("A、B比较返回大值:" + bigA.max(bigB));
19 }
20 }
程序的运行结果如下:
A+B的值:300000
A-B的值:-100000
A×B的值:20000000000
A÷B的值:0
取余数:100000
A÷B的值(返回数组):--商:0--余数:100000
A取相反数:-100000
A、B比较返回小值:100000
A、B比较返回大值:200000
9.6.3 Random类
Random类位于java.util包中,该类用于生成一个伪随机数,也就是按照一定规则生成的随机数。在进行随机数生成时,随机算法的起源数字被称之为种子数(seed),在种子数的基础上按照相应规则进行变换,从而产生需要的随机数字。相同种子数的Random对象,相同次数生成的随机数字是完全相同的。
该类有两个构造方法:一个构造方法使用默认的种子(以当前时间作为种子),另一个构造方法需要我们显示传入一个long型整数的种子:
public Random() // 以当前时间作为种子
public Random(long seed) // 自定义随机数生成器种子
与Math类中的random()方法相比,Random类提供了更多的方式来生成各种伪随机数,既可以生成浮点类型的伪随机数,也可以生成整数类型的伪随机数,并且还可以指定生成随机数的范围。
Random类中常用的方法如表9.25所示。
表9.25 Random类常用方法
方法 |
方法描述 |
boolean nextBoolean() |
返回一个随机的布尔值 |
double nextDouble() |
返回一个随机的双精度型值 |
int nextInt() |
返回一个随机整数 |
int nextInt(int bound) |
返回一个0-n之间的随机整数 |
void setSeed(long seed) |
设置Random对象中的种子数 |
long nextLong() |
返回一个随机长整型值 |
float nextFloat() |
返回一个随机浮点型值 |
接下来演示Random类常用方法的使用,如例9-34所示。
例9-34 Demo0934.java
1 package com.aaa.p0906;
2 import java.util.Random;
3 public class Demo0934 {
4 public static void main(String[] args) {
5 Random r1 = new Random();
6 double num1 = r1.nextDouble(); // 生成一个[0,1.0)区间的小数
7 System.out.println("[0,1.0)区间小数:" + num1);
8 double num2 = r1.nextDouble()*2; // 生成一个[0,2.0)区间的小数
9 System.out.println("[0,2.0)区间的小数:" + num2);
10 int num3 = r1.nextInt(); // 生成一个任意整数
11 System.out.println("随机整数:" + num3);
12 int num4 = r1.nextInt(5); //生成一个[0,5)区间的整数
13 System.out.println("[0,5)区间的整数:" + num4);
14 int num5 = r1.nextInt(18) - 3; // 生成一个[-3,15)区间的整数
15 System.out.println("[-3,15)区间的整数:" + num5);
16 // 相同种子数的Random对象,相同次数生成的随机数字是相同的
17 Random r2 = new Random(20);
18 Random r3 = new Random(20);
19 for (int i = 0;i<5;i++) {
20 System.out.println("r2生成整数:" + (r2.nextInt(18) - 3));
21 System.out.println("r3生成整数:" + (r3.nextInt(18) - 3));
22 }
23 }
24 }
程序的运行结果如下:
[0,1.0)区间小数:0.8630062058747404
[0,2.0)区间的小数:0.7852189438727106
随机整数:1533148188
[0,5)区间的整数:2
[-3,15)区间的整数:0
r2生成整数:14
r3生成整数:14
r2生成整数:13
r3生成整数:13
r2生成整数:6
r3生成整数:6
r2生成整数:12
r3生成整数:12
r2生成整数:2
r3生成整数:2
9.6.4数字格式化
Java语言中,提供了两个可以用于完成数字的格式化的类,一个是NumberFormat类,一个是DecimalFormat类。
1.NumberFormat类格式化
NumberFormat类用于解析和格式化任何语言环境的数字,可以按照本地的语言风格进行数字的显示。例如,可以将一个数值格式化为符合某个国家地区习惯的数值字符串,也可以将符合某个国家地区习惯的数值字符串解析为相应的数值。同时,NumberFormat类也是一个抽象类,是Format类的子类,不能直接通过new关键字来进行对象的创建。NumberFormat类提供了很多静态方法用于获取一个该类的实例对象,具体如表9.26所示。
表9.26 NumberFormate类的对象获取方法
方法 |
方法描述 |
static NumberFormat getInstance() |
返回默认语言环境的通用数值格式 |
static NumberFormat getInstance(Locale inLocale) |
返回指定语言环境的通用数值格式 |
static NumberFormat getCurrencyInstance() |
返回当前默认语言环境的货币格式 |
static NumberFormat getCurrencyInstance(Locale inLocale) |
返回指定环境的货币格式 |
static final NumberFormat getIntegerInstance() |
返回当前默认环境的整数格式 |
static NumberFormat getIntegerInstance(Locale inLocale) |
返回指定语言环境的整数格式 |
static final NumberFormat getNumberInstance() |
返回当前默认环境的通用数值 |
static NumberFormat getNumberInstance(Locale inLocale) |
返回指定语言环境的通用数值 |
static final NumberFormat getPercentInstance() |
返回当前默认环境的百分比格式 |
static NumberFormat getPercentInstance(Locale inLocale) |
返回指定语言环境的百分比格式 |
另外,NumberFormat类提供的常用方法主要有两个,具体如表9.27所示。
表9.27 NumberFormate类的常用方法
方法 |
方法描述 |
String format(数值) |
将某个数值格式化为符合某个国家地区习惯的数值字符串 |
Number parse(String source) |
将符合某个国家地区习惯的数值字符串解析为对应的数值 |
接下来演示NumberFormat类常用方法的使用,如例9-35所示。
例9-35 Demo0935.java
1 package com.aaa.p0906;
2 import java.text.NumberFormat;
3 import java.text.ParseException;
4 import java.util.Locale;
5 public class Demo0935 {
6 public static void main(String[] args) throws ParseException {
7 NumberFormat nf = NumberFormat.getInstance();
8 // 将数值格式化为符合某个国家地区习惯的数值字符串
9 int price = 13;
10 System.out.println("price:" + price);
11 System.out.println("以默认语言格式化price:" + nf.format(price));
12 nf = NumberFormat.getCurrencyInstance(Locale.US);
13 System.out.println("以US格式化price:" + nf.format(price));
14 nf = NumberFormat.getCurrencyInstance(Locale.FRANCE);
15 System.out.println("以FRANCE格式化price:" + nf.format(price));
16 // 将符合某个国家地区习惯的数值字符串解析为对应的数值
17 nf = NumberFormat.getCurrencyInstance(Locale.US);
18 String str = "$13.00";
19 Number n = nf.parse(str);
20 System.out.println("将$13.00格式化为数值:" + n.doubleValue());
21 //其他格式化
22 double d = 0.35;
23 nf = NumberFormat.getPercentInstance();
24 System.out.println("0.35的百分比:" + nf.format(d));
25 }
26 }
程序的运行结果如下:
price:13
以默认语言格式化price:13
以US格式化price:$13.00
以FRANCE格式化price:13,00 €
将$13.00格式化为数值:13.0
0.35的百分比:35%
2.DecimalFormat类格式化
DecimalFormat类是NumberFormat类的一个具体子类,用于格式化十进制数字。使用该类格式化数字的时候要比直接使用NumberFormat 更加方便,因为可以直接按照用户自定义的方式进行相应的格式化操作,同时也支持解析和格式化任何语言环境以及不同类型的数字,包括整数、小数、科学计数法、百分比和货币金额等。需要注意的是:对于数值的小数部分,默认只是显示3位小数,当超出小数点3位时,采用四舍五入的方法进行舍弃。DecimalFormat类常用的实例化方法如表9.28所示。
表9.28 DecimalFormat类常用的实例化方法
方法 |
方法描述 |
new DecimalFormat() |
构造方法,使用默认语言环境的默认模式和符号创建对象 |
new DecimalFormat(String pattern) |
构造方法,指定规则进行对象创建 |
DecimalFormat类除了提供了format()方法和parse()方法之外,还提供了applyPattern(String pattern) 方法来自定义格式化规则。
接下来演示DecimalFormat类常用方法的使用,如例9-36所示。
例9-36 Demo0936.java
1 package com.aaa.p0906;
2 import java.text.DecimalFormat;
3 import java.text.ParseException;
4 public class Demo0936 {
5 public static void main(String[] args) throws ParseException {
6 double PI = 3.1415926;
7 DecimalFormat df0 = new DecimalFormat();
8 df0.applyPattern("0.0000"); // 设置格式规则
9 System.out.println("PI_0:" + df0.format(PI)); // 将数字格式化成指定格式的字符串
10 DecimalFormat df1 = new DecimalFormat("0.000");
11 System.out.println("PI_1:" + df1.format(PI));
12 String numStr = "11.111";
13 Number num = df1.parse(numStr); // 将字符串解析为对应的数值
14 System.out.println("df1.parse(numStr):" + num.doubleValue());
15 }
16 }
程序的运行结果如下:
PI_0:3.1416
PI_1:3.142
df1.parse(numStr):11.111
除了以上这种基本使用方法外,DecimalFormat类还支持使用不同的符号来代表不同的格式,常用符号以及代表意义如表9.29示。
表9.29 DecimalFormat类支持的符号含义
符号 |
位置 |
是否本地化 |
含义 |
0 |
数字 |
是 |
阿拉伯数字 |
# |
数字 |
是 |
阿拉伯数字,如果不存在则显示为空 |
. |
数字 |
是 |
小数分隔符或货币小数分隔符 |
- |
数字 |
是 |
减号 |
, |
数字 |
是 |
分组分隔符 |
E |
数字 |
是 |
分隔科学计数法中的尾数和指数。在前缀或后缀中无需加引号 |
; |
子模式边界 |
是 |
分隔正数和负数子模式 |
% |
前缀或后缀 |
是 |
乘以 100 并显示为百分数 |
/u2030 |
前缀或后缀 |
否 |
乘以 1000 并显示为千分数 |
¤(/u00A4) |
前缀或后缀 |
否 |
货币记号,由货币符号替换。如果两个同时出现,则用国际货币符号替换。如果出现在某个模式中,则使用货币小数分隔符,而不使用小数分隔符。 |
' |
前缀或后缀 |
否 |
用于在前缀或或后缀中为特殊字符加引号,例如 "'#'#" 将 123 格式化为 "#123"。要创建单引号本身,请连续使用两个单引号:"# o''clock" |
接下来演示DecimalFormat类不同符号使用的测试,具体如例9-37所示。
例9-37 Demo0937.java
1 package com.aaa.p0906;
2 import java.text.DecimalFormat;
3 import java.text.ParseException;
4 public class Demo0937 {
5 public static void main(String[] args) throws ParseException {
6 double d = 156.82359646;
7 // 符号0代表数字——此规则含义为:数值位数够,取所有整数,按照四舍五入舍弃小数;
8 DecimalFormat f1 = new DecimalFormat("0");
9 System.out.println("符号0:" + f1.format(d));
10 // 此规则含义:数值位数不够按照格式补0(小数整数都补)
11 f1 = new DecimalFormat("0000.00000000000");
12 System.out.println("符号0:" + f1.format(d));
13 // 符号#代表数字,如果不存在则显示为空
14 // 此规则含义:数值位数够,取所有整数,按照四舍五入舍弃小数;
15 f1 = new DecimalFormat("#");
16 System.out.println("符号#:" + f1.format(d));
17 // 此规则含义:数值位数不够,不进行补充;
18 f1 = new DecimalFormat("####.###########");
19 System.out.println("符号#:" + f1.format(d));
20 // 符号%代表乘以 100并显示为百分数
21 f1 = new DecimalFormat("#.##%");
22 System.out.println("百分比方式计数且保留2位小数:" + f1.format(d));
23 int number = 123456789;
24 // 符号,代表分组分隔符
25 f1 = new DecimalFormat(",##");
26 System.out.println("两位一组进行分隔:" + f1.format(number));
27 // 符号E:科学计数
28 f1 = new DecimalFormat("00.####E0");
29 System.out.println("科学计数法并保留2位整数4位小数:" + f1.format(number));
30 }
31 }
程序的运行结果如下:
符号0:157
符号0:0156.82359646000
符号#:157
符号#:156.82359646
百分比方式计数且保留2位小数:15682.36%
两位一组进行分隔:1,23,45,67,89
科学计数法并保留2位整数4位小数:12.3457E7
9.7 本章小结
• Java语言中提供了String类、StringBuffer类和StringBuilder类用来做字符串处理,String类型是不可变字符串,StringBuffer类型和StringBuilder类型是可变字符串,StringBuilder类是StringBuffer类的简化,速度快但线程安全性差。
• 日期处理类有很多个,其中Date类用来处理日期,Calendar类用来处理日历。目前,Date类的很多方法都已经不推荐使用,逐渐被JDK8中新增的LocalDate类、LocalTime类、LocalDateTime类及其对应方法所取代。
• Java语言提供了SimpleDateFormat类来实现Date对象和字符串对象之间按照指定格式进行转换,DateTimeFormatter类来实现LocalDate对象、LocalDateTime对象、LocalTime对象和字符串对象之间的转换。
• System类可以用来获取系统相关信息。
• Runtime类可以用来查看JVM运行环境信息。
• Java无法将基本数据类型视为对象操作,可以通过封装类将其封装成对象来处理。
• Math类有很多数学运算方法,其中random()方法可以生成随机数。
• Random类提供了更多的方式来生成各种伪随机数,可以指定生成随机数的范围。
• Java提供了NumberFormat类、DecimalFormat类来实现数字和字符串之间按照指定格式进行转换。
9.8 理论试题与实践练习
1.填空题
1.%2 比较两个字符串是否相同应该使用 方法。
2.%2 String str = "AAA软件教育";int len = str.length(),len的值为 。
3.%2 Math.round(21.5)的结果是 ,Math.round(-21.5)的结果是 。
4.%2 格式化Date日期用 类,格式化LocalDatetime用 类。
2.选择题
2.1已知有定义:String s="AAA软件教育",下面表达式正确的是( )
A.s+="you"; B.char c=s[1];
C.int len=s.length; D.String str = str.charAt(10);
2.2 对于下列代码:
String str1 = "AAA软件教育";
String str2 = "AAA软件教育";
String str3 = new String("AAA软件教育");
StringBuffer str4 = new StringBuffer("AAA软件教育");
以下表达式返回true的是( )
A、str1==str2 B、str2==str3
C、str1==str4 D、str3==str4
2.3 下列属于引用数据类型是( )
A、char B、int C、long D、String
2.4 下面不是String类提供的合法方法的是( )
A、equals() B、append() C、indexOf() D、trim()
2.5 给定如下所示的Java代码:String s = null;s.concat("abc");该代码在运行时会产生什么类型的异常( )。
A、ArithmeticException B、NullPointerException
C、IOException D、ClassNotFoundException
3.思考题
3.1 请简述String、StringBuffer类的区别?
3.2 String s = ”Hello”;s = s + ”world!”,这两行代码执行后,原始的String对象中的内容是否会发生改变?
3.3 String类是否可以被继承?
3.4 String s = new String(“abc”);这行代码创建了几个对象,区别是什么?
3.5 对String对象而言, “==” 和 equals() 的区别?
3.6 分别简述一下LocalDate、LocalTime、LocalDateTime类的区别?
4.编程题
4.1 输入一个手机号,将中间四位使用星号替代。
4.2 分别在控制台输入字符串和子字符串,并计算字符串中子字符串出现的次数。
4.3 输入整数,分别输出其二进制、八进制、十六进制的表示。
- 点赞
- 收藏
- 关注作者
评论(0)