第5章 Java中的常用类
String 与 StringBuffer、System 与 Runtime、包装类、格式化类、日期时间类。
本章学习目标
- 掌握 String 的常用操作与不可变性
- 能用 StringBuffer/StringBuilder 做可变字符串
- 会用包装类做字符串与基本类型互转
- 会用 SimpleDateFormat/DateFormat 格式化日期
本章导览
核心内容
格式化类
日期与时间类
格式化类
目录
在JDK的java.util包中,提供了一个Date类用于表示日期和时间。
随着JDK版本的不断升级和发展,Date类中大部分的构造方法和普通方法都已经不再推荐使用。
目前JDK 8中,Date类只有两个构造方法是可以使用的。
Date():用来创建当前日期时间的Date对象。
Date(long date):用于创建指定时间的Date对象,其中date参数表示1970年1月1日0时0分0(称为历元)以来的毫秒数,即时间戳。
Calendar类用于完成日期和时间字段的操作,它可以通过特定的方法设置和读取日期的特定部分,比如年、月、日、时、分和秒等。
Calendar类是一个抽象类,不可以被实例化。
在程序中需要调用其静态方法getInstance()来得到一个Calendar对象,然后才能调用其相应的方法。
Calendar calendar = Calendar.getInstance();| 方法声明 | 功能描述 |
|---|---|
| int get(int field) | 返回指定日历字段的值 |
| void add(int field,int amount) | 根据日历规则,为指定的日历字段增加或减去指定的时间量 |
| void set(int field,int value) | 为指定日历字段设置指定值 |
| void set(int year,int month,int date) | 设置Calendar对象的年、月、日三个字段的值 |
| void set(int year.int month,int date,int hourOfDay,int minute,int second) | 设置Calendar对象的年、月、日、时、分、秒六个字段的值 |
案例演示(参考教材文件5-20&5-21)
注
Calendar日历容错模式与非容错模式
Calendar有两种解释日历字段的模式——lenient模式(容错模式)和non-lenient模式(非容错模式)。当Calendar处于lenient模式时,它的字段可以接收超过允许范围的值,当调用get(int field)方法获取某个字段值时,Calendar会重新计算所有字段的值,将字段的值标准化。
案例演示(参考教材文件5-22)
多
学
一
招
| 类名 | 功能描述 |
|---|---|
| Clock | 用于获取指定时区的当前日期、时间。 |
| DayOfWeek | 枚举类,定义了一周七天周一到周日的枚举值 |
| Duration | 表示持续时间。该类提供的ofXxx()方法用于获取指定的时间的小时、分钟、秒数等。 |
| Instant | 表示一个具体时刻,可以精确到纳秒。该类提供了静态的now()方法来获取当前时刻,提供了静态的now(Clock clock)方法来获取clock对应的时刻。同时还提供了一系列的plusXxx()方法来获取当前时刻基础上加上一段时间,以及一系列的minusXxx()方法在当前时刻基础上减去一段时间。 |
为了满足更多的需求,JDK 8中新增了一个java.time包,在该包下包含了更多的日期和时间操作类。
| 类名 | 功能描述 |
|---|---|
| LocalDate | 表示不带时区的日期,如2018-01-27。该类提供了静态的now()方法来获取当前日期,提供了静态的now(Clock clock)方法来获取clock对应的日期。同时还提供了一系列的plusXxx()方法在当前年份基础上加上几年、几月、几日等,以及一系列的minusXxx()方法在当前年份基础上减去几年、几月、几日等。 |
| LocalTime | 表示不带时区的时间,如14:49:20。该类提供了静态的now()方法来获取当前时间,提供了静态的now(Clock clock)方法来获取clock对应的时间。同时还提供了一系列的plusXxx()方法在当前年份基础上加上几小时、几分、几秒等,以及一系列的minusXxx()方法在当前年份基础上减去几小时、几分、几秒等。 |
| LocalDateTime | 表示不带时区的日期、时间。该类提供了静态的now()方法来获取当前日期、时间,提供了静态的now(Clock clock)方法来获取clock对应的日期、时间。同时还提供了一系列的plusXxx()方法在当前年份基础上加上几年、几月、几日、几小时、几分、几秒等,以及一系列的minusXxx()方法在当前年份基础上减去几年、几月、几日、几小时、几分、几秒等。 |
| Month | 枚举类,定义了一月到十二月的枚举值 |
| MonthDay | 表示月日,如--01-27。该类提供了静态的now()方法来获取当前月日,提供了静态的now(Clock clock)方法来获取clock对应的月日。 |
📄 展开课件原文(第 4–39 页,共 7 页)
String类与StringBuffer类
Java中是怎样操作字符串的?
Java中定义了String和StringBuffer两个类来封装字符串,并提供了一系列操作字符串的方法。由于他们都位于java.lang包中,因此不需要导包就可以直接使用。
使用字符串常量直接初始化一个String对象。
String 变量名= 字符串;在初始化字符串对象时,既可以将字符串对象的初始化值设为空,也可以初始化为一个具体的字符串。
String str1 = null; // 初始化为空
String str2 = ""; // 初始化为空字符串
String str3 = "abc"; // 初始化为abc,其中abc为字符串常量使用String的构造方法初始化字符串对象。
String 变量名 = new String(字符串);上述语法中,字符串同样可以为空或是一个具体的字符串。当为具体字符串时,会使用String类的不同参数类型的构造方法来初始化字符串对象。
String类中常用的构造方法:
| 方法声明 | 功能描述 |
|---|---|
| String() | 创建一个内容为空的字符串 |
| String(String value) | 根据指定的字符串内容创建对象 |
| String(char[] value) | 根据指定的字符数组创建对象 |
基本操作
转换操作
替换和去空操作
String类
常见操作
判断操作
截取和分隔操作
如获得字符串长度、获得指定位置的字符等。
如将字符串转换成字符数组、将字符串中的字符进行大小写转换等。
如可以使用String类的replace()和trim()方法,进行字符串的替换和去除空格操作。
如判断字符串是否以指定的字符串开始、结束,是否包含指定的字符串,字符串是否为空等。
如substring()方法用于截取字符串的一部分,split()方法可以将字符串按照某个字符进行分割。
String字符串在获取某个字符时,会用到字符的索引,当访问字符串中的字符时,如果字符的索引不存在,则会发生StringIndexOutOfBoundsException(字符串角标越界异常)。
String s = "abcde";
System.out.println(s.charAt(10));访问字符串中的字符时,不能超出字符的索引范围,否则会出现异常,这与数组中的角标越界异常相似。
脚
下
留
心
StringBuilder的使用
除了使用StringBuffer外,JDK 1.5之后提供了一个StringBuilder类同样可以操作字符串。StringBuilder与StringBuffer的功能相似,且两个类中所提供的方法也基本相同。
主要区别:二者所不同的是StringBuffer是线程安全的,而StringBuilder没有实现线程安全功能,所以性能略高。通常情况下,如果创建一个内容可变的字符串对象,应该优先考虑StringBuilder类。
多
学
一
招
📄 展开课件原文(第 10–20 页,共 6 页)
String类的常见操作——String类的常用方法
| 方法声明 | 功能描述 |
|---|---|
| int indexOf(int ch) | 返回指定字符在此字符串中第一次出现处的索引 |
| int lastIndexOf(int ch) | 返回指定字符在此字符串中最后一次出现处的索引 |
| int indexOf(String str) | 返回指定子字符串在此字符串中第一次出现处的索引 |
| int lastIndexOf(String str) | 返回指定子字符串在此字符串中最后一次出现处的索引 |
| char charAt(int index) | 返回字符串中index位置上的字符,其中index的取值范围是:0~(字符串长度-1) |
| boolean endsWith(String suffix) | 判断此字符串是否以指定的字符串结尾 |
| int length() | 返回此字符串的长度 |
| boolean equals(Object anObject) | 将此字符串与指定的字符串比较 |
| boolean isEmpty() | 当且仅当字符串长度为0时返回true |
| boolean startsWith(String prefix) | 判断此字符串是否以指定的字符串开始 |
| boolean contains(CharSequence cs) | 判断此字符串中是否包含指定的字符序列 |
| 方法声明 | 功能描述 |
|---|---|
| String toLowerCase() | 使用默认语言环境的规则将String中的所有字符都转换为小写 |
| String toUpperCase() | 使用默认语言环境的规则将String中的所有字符都转换为大写 |
| static String valueOf(int i) | 返回 int 参数的字符串表示形式 |
| char[] toCharArray() | 将此字符串转换为一个字符数组 |
| String replace(CharSequence oldstr, CharSequence newstr) | 返回一个新的字符串,它是通过用newstr替换此字符串中出现的所有oldstr得到的 |
| String[] split(String regex) | 根据参数regex(regex是一个正则表达式,用来限定分隔规则)将字符串分割为若干个子字符串 |
| String substring(int beginIndex) | 返回一个新字符串,它包含从指定的beginIndex起始角标处开始,直到此字符串末尾的所有字符 |
| String substring(int beginIndex, int endIndex) | 返回一个新字符串,它包含从指定的beginIndex起始角标处开始,直到索引endIndex-1角标处的所有字符 |
| String trim() | 返回一个新字符串,它去除了原字符串首尾的空格 |
📄 展开课件原文(第 13–14 页,共 2 页)
StringBuffer类
在Java中,由于String类是final类型的,所以使用String定义的字符串是一个常量,因此它一旦创建,其内容和长度是不可改变的。如果需要对一个字符串进行修改,则只能创建新的字符串。
解决方法:可以使用StringBuffer类(也称字符串缓冲区)来操作字符串。
说明:StringBuffer类和String类最大的区别在于它的内容和长度都是可以改变的。StringBuffer类似一个字符容器,当在其中添加或删除字符时,所操作的都是这个字符容器,因此并不会产生新的StringBuffer对象。
| 方法声明 | 功能描述 |
|---|---|
| StringBuffer append(char c) | 添加字符到StringBuffer对象中末尾 |
| StringBuffer insert(int offset,String str) | 在StringBuffer对象中的offset位置插入字符串str |
| StringBuffer deleteCharAt(int index) | 移除StringBuffer对象中指定位置的字符 |
| StringBuffer delete(int start,int end) | 删除StringBuffer对象中指定范围的字符或字符串 |
| StringBuffer replace(int start,int end,String s) | 将StringBuffer对象中指定范围的字符或字符串用新的字符串s进行替换 |
| void setCharAt(int index, char ch) | 修改指定位置index处的字符 |
| String toString() | 返回StringBuffer缓冲区中的字符串对象 |
| StringBuffer reverse() | 将此StringBuffer对象用其反转形式取代 |
StringBuffer类和String类的对比分析如下:
String类定义的字符串是常量,一旦创建后,内容和长度都是无法改变的。StringBuffer表示字符容器,其内容和长度可以随时修改。
String类重写了Object类的equals()方法,而StringBuffer类没有重写Object类的equals()方法。
📄 展开课件原文(第 17–19 页,共 3 页)
System类与Runtime类
System类定义了一些与系统相关的属性和方法,它所提供的属性和方法都是静态的,因此,想要引用这些属性和方法,直接使用System类调用即可。
System类的常用方法如下:
| 方法声明 | 功能描述 |
|---|---|
| static void exit(int status) | 该方法用于终止当前正在运行的Java虚拟机,其中参数status表示状态码,若状态码非0 ,则表示异常终止 |
| static void gc() | 运行垃圾回收器,并对垃圾进行回收 |
| static native long currentTimeMillis() | 返回以毫秒为单位的当前时间 |
| static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length) | 从src引用的指定源数组复制到dest引用的数组,复制从指定的位置开始,到目标数组的指定位置结束 |
| static Properties getProperties() | 取得当前的系统属性 |
| static String getProperty(String key) | 获取指定键描述的系统属性 |
getProperties()
arraycopy()
currentTimeMillis()
该方法用于获取当前系统的全部属性该方法会返一个Properties对象,其中封装了系统的所有属性,这些属性是以键值对形式存在的。
该方法返回一个long类型的值,该值表示当前时间与1970年1月1日0点0分0秒之间的时间差,单位是毫秒,通常也将该值称作时间戳。
该方法用于将一个数组中的元素快速拷贝到另一个数组。
src:表示源数组;
dest:表示目标数组;
srcPos:表示源数组中拷贝元素的起始位置;
destPos:表示拷贝到目标数组的起始位置;
length:表示拷贝元素的个数。
定义:Runtime类用于表示Java虚拟机运行时的状态,它用于封装Java虚拟机进程。
说明:每次使用“java”命令启动Java虚拟机时都会对应一个Runtime实例,并且只有一个实例,应用程序会通过该实例与其运行时的环境相连。
获取Runtime实例方式:
Runtime run = Runtime.getRuntime();注意:Runtime类中提供了一个exec()方法,该方法用于执行一个DOS命令,从而实现和在命令行窗口中输入DOS命令同样的效果。
📄 展开课件原文(第 21–23 页,共 3 页)
Math类与Random类
Math类是一个工具类,主要用于完成复杂的数学运算,如求绝对值、三角函数、指数运算等。
由于Math类的构造方法被定义成private,因此无法创建Math类的对象。
Math类中的所有方法都是静态方法,可以直接通过类名来调用它们。
除静态方法外,Math类中还有两个静态常量PI和E,分别代表数学中的π和e。
案例演示(参考教材文件5-15)
在JDK的java.util包中,有一个Random类,它可以在指定的取值范围内随机产生数字。
Random类的两个构造方法:
| 方法声明 | 功能描述 |
|---|---|
| Random() | 构造方法,用于创建一个随机数生成器,每次实例化Random对象会生成不同的随机数 |
| Random(long seed) | 构造方法,使用一个long型的seed(种子)创建伪随机数生成器,当seed相同时,每次实例化Random对象会生成相同的随机数 |
| 方法声明 | 功能描述 |
|---|---|
| boolean nextBoolean() | 随机生成boolean类型的随机数 |
| double nextDouble() | 随机生成double类型的随机数 |
| float nextFloat() | 随机生成float类型的随机数 |
| int nextInt() | 随机生成int类型的随机数 |
| int nextInt(int n) | 随机生成[0,n)之间int类型的随机数 |
| long nextLong() | 随机生成long类型的随机数 |
案例演示(参考教材文件5-16)
📄 展开课件原文(第 24–26 页,共 3 页)
包装类
虽然Java是面向对象的编程语言,但它所包含的8种基本数据类型却不支持面向对象的编程机制(没有属性和方法)。在Java中,很多类的方法都需要接收引用类型的对象,此时就无法将一个基本数据类型的值传入。为了解决这样的问题,JDK中提供了一系列的包装类,通过这些包装类可以将基本数据类型的值包装为引用数据类型的对象。
为什么需要包装类?
基本类型——包装类对照表:
| 基本数据类型 | 对应的包装类 |
|---|---|
| byte | Byte |
| char | Character |
| int | Integer |
| short | Short |
| long | Long |
| float | Float |
| double | Double |
| boolean | Boolean |
自动装箱(Autoboxing):是指将基本数据类型的变量赋给对应的包装类变量;
自动拆箱(AutoUnboxing):是指将包装类对象类型直接赋给一个对应的基本数据类型变量。
案例演示(参考教材文件5-17)
基本数据类型、基本数据包装类以及字符串之间的相互转换:
通过引用数据类型字符串String类的valueOf()方法可以将8种基本数据类型转换为对应的字符串类型;
通过8种包装类的静态方法valueOf()既可以将对应的基本数据类型转换为包装类,也可以将变量内容匹配的字符串转换为对应的包装类(Character包装类除外);
通过8种包装类的有参构造方法同样既可以将对应的基本数据类型转换为包装类,也可以将变量内容匹配的字符串转换为对应的包装类(Character包装类除外);
通过8种包装类的静态方法parseXxx()可以将变量内容匹配的字符串转换为对应的基本数据类型;
包装类都重写了Object类中的toString()方法,以字符串的形式返回被包装的基本数据类型的值。
案例演示(参考教材文件5-18)
使用valueOf(String s)和parseXxx(String s)方法注意事项:
除了Character外,包装类都有valueOf(String s)方法,可以根据String类型的参数创建包装类对象,但参数字符串s不能为null,而且字符串必须是可以解析为相应基本类型的数据,否则虽然编译通过,但运行时会报错。
Integer i = Integer.valueOf("123"); // 合法
Integer i = Integer.valueOf("12a"); // 不合法除了Character外,包装类都有parseXxx(String s)的静态方法,将字符串转换为对应的基本类型的数据。参数s不能为null,而且同样必须是可以解析为相应基本类型的数据,否则虽然编译通过,但运行时会报错。
int i = Integer.parseInt("123"); // 合法
Integer in = Integer.parseInt("itcast"); // 不合法| 类名 | 功能描述 |
|---|---|
| Year | 表示年,如2018。该类提供了静态的now()方法来获取当前年份,提供了静态的now(Clock clock)方法来获取clock对应的年份。同时还提供了plusYears()方法在当前年份基础上增加几年,以及minusYears()方法在当前年份基础上减去几年。 |
| YearMonth | 表示年月,如2018-01。该类提供了静态的now()方法来获取当前年月,提供了静态的now(Clock clock)方法来获取clock对应的年月。同时还提供了plusXxx()方法在当前年月基础上增加几年、几月,以及minusXxx()方法在当前年月基础上减去几年、几月。 |
| ZoneId | 表示一个时区 |
| ZonedDateTime | 表示一个时区化的日期、时间 |
| Year | 表示年,如2018。该类提供了静态的now()方法来获取当前年份,提供了静态的now(Clock clock)方法来获取clock对应的年份。同时还提供了plusYears()方法在当前年份基础上增加几年,以及minusYears()方法在当前年份基础上减去几年。 |
📄 展开课件原文(第 27–40 页,共 8 页)
格式化类
作用:DateFormat类专门用于将日期格式化为字符串或者将用特定格式显示的日期字符串转换成一个Date对象。
说明:DateFormat是一个抽象类,不能被直接实例化,但它提供了一系列的静态方法来获取DateFormat类的实例对象,并能调用其他相应的方法进行操作。
| 方法声明 | 功能描述 |
|---|---|
| static DateFormat getDateInstance() | 用于创建默认语言环境和格式化风格的日期格式器 |
| static DateFormat getDateInstance(int style) | 用于创建默认语言环境和指定格式化风格的日期格式器 |
| static DateFormat getDateTimeInstance() | 用于创建默认语言环境和格式化风格的日期/时间格式器 |
| static DateFormat getDateTimeInstance( int dateStyle,int timeStyle) | 用于创建默认语言环境和指定格式化风格的日期/时间格式器 |
| String format(Date date) | 将一个 Date 格式化为日期/时间字符串。 |
| Date parse(String source) | 将给定字符串解析成一个日期 |
FULL
LONG
MEDIUM
常用
常量
SHORT
用于表示完整格式。
用于表示长格式。
用于表示普通格式。
用于表示短格式。
在使用DateFormat对象的parse()方法将字符串解析为日期时,需要输入固定格式的字符串,这显然不够灵活。为了能够更好地格式化日期、解析字符串,Java中提供了一个SimpleDateFormat类。
说明:SimpleDateFormat类是DateFormat类的子类,它可以使用new关键字创建实例对象。在创建实例对象时,它的构造方法需要接收一个表示日期格式模板的字符串参数。
使用SimpleDateFormat类将日期对象以特定的格式转为字符串形式:
SimpleDateFormat sdf = new SimpleDateFormat("Gyyyy年MM月dd日:今天是yyyy年的第D天,E");
System.out.println(sdf.format(new Date()));使用SimpleDateFormat类将一个指定日期格式的字符串解析为Date对象:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
String str = "2018/01/27";
System.out.println(sdf.parse(str));JDK 8在java.time.format包下还提供了一个DateTimeFormatter类,该类也是一个格式化类,其功能相当于DataFormat和SimpleDateFormat的合体,它不仅可以将日期、时间对象格式化成字符串,还能将特定格式的字符串解析成日期、时间对象。
要使用DateTimeFormatter进行格式化或者解析,就必须先获得DateTimeFormatter对象。
使用静态常量创建DateTimeFormatter格式器。
在DateTimeFormatter类中包含大量的静态常量,如BASIC_ISO_DATE、ISO_LOCAL_DATE、ISO_LOCAL_TIME等,通过这些静态常量都可以获取DateTimeFormatter实例。
使用不同风格的枚举值来创建DateTimeFormatter格式器。
在FormatStyle类中定义了FULL、LONG、MEDIUM和SHORT四个枚举值,它们表示日期和时间的不同风格。
根据模式字符串创建DateTimeFormatter格式器。
完成日期、时间格式化
调用DateTimeFormatter的format(TemporalAccessor temporal)方法执行格式化。其中参数temporal是一个TemporalAccessor类型接口,其主要实现类有LocalDate、LocalDateTime。
调用LocalDate、LocalDateTime等日期、时间对象的format(DateTimeFormatter formatter)方法执行格式化。
将日期、时间格式化为字符串
案例演示(参考教材文件5-28)
解析字符串
可以通过日期时间对象所提供的parse(CharSequence text, DateTimeFormatter formatter)方法来实现。
将指定格式的字符串解析成日期、时间对象
案例演示(参考教材文件5-29)
📄 展开课件原文(第 41–49 页,共 9 页)
本章小结
本章主要讲解了Java中常用的一些类的使用。首先讲解了处理字符串的String类和StringBuffer类的使用,然后讲解了系统相关的System类和Runtime类常的使用,以及Math类和Random类、Java中包装类的相关知识。接下来讲解了Java中的日期、时间类以及格式化器类的使用。
📄 展开课件原文(第 50–51 页,共 2 页)
课件里的提醒 课件原文中的“注意 / 说明 / 定义”
- 说明:StringBuffer类和String类最大的区别在于它的内容和长度都是可以改变的。StringBuffer类似一个字符容器,当在其中添加或删除字符时,所操作的都是这个字符容器,因此并不会产生新的StringBuffer对象。
- 定义:Runtime类用于表示Java虚拟机运行时的状态,它用于封装Java虚拟机进程。
- 说明:每次使用“java”命令启动Java虚拟机时都会对应一个Runtime实例,并且只有一个实例,应用程序会通过该实例与其运行时的环境相连。
- 注意:Runtime类中提供了一个exec()方法,该方法用于执行一个DOS命令,从而实现和在命令行窗口中输入DOS命令同样的效果。
- 说明:DateFormat是一个抽象类,不能被直接实例化,但它提供了一系列的静态方法来获取DateFormat类的实例对象,并能调用其他相应的方法进行操作。
- 说明:SimpleDateFormat类是DateFormat类的子类,它可以使用new关键字创建实例对象。在创建实例对象时,它的构造方法需要接收一个表示日期格式模板的字符串参数。
本章代码速览 把课件里的示例代码集中起来,可直接复制运行
String 变量名= 字符串;String str1 = null; // 初始化为空String str2 = ""; // 初始化为空字符串String str3 = "abc"; // 初始化为abc,其中abc为字符串常量String 变量名 = new String(字符串);String s = "abcde";System.out.println(s.charAt(10));Runtime run = Runtime.getRuntime();Integer i = Integer.valueOf("123"); // 合法Integer i = Integer.valueOf("12a"); // 不合法int i = Integer.parseInt("123"); // 合法Integer in = Integer.parseInt("itcast"); // 不合法