1. String类
1.1 简介
- String类: 代表字符串。 Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
- String是一个final类,代表不可变的字符序列。
- 字符串是常量,用双引号引起来表示。 它们的值在创建之后不能更改。
- String对象的字符内容是存储在一个字符数组value[]中的。
代码:
String s1 = "Runoob"; // String 直接创建
String s2 = "Runoob"; // String 直接创建
String s3 = s1; // 相同引用
String s4 = new String("Runoob"); // String 对象创建
String s5 = new String("Runoob"); // String 对象创建
s1、2、3存在于字符串常量池中 s4、5是new出来的对象所以存在堆中
1.2 String的内存结构
案例对比
1.3 字符串拼接
编译器可以确定的字符串存在常量池里
编译期不能确定的字符串存在堆里
intern()方法,返回对应常量池的字符序列
1.4 常用方法
- nt length(): 返回字符串的长度: return value.length
- char charAt(int index): 返回某索引处的字符return value[index]
- boolean isEmpty(): 判断是否是空字符串: return value.length == 0
- String toLowerCase(): 使用默认语言环境, 将 String 中的所有字符转换为小写
- String toUpperCase(): 使用默认语言环境, 将 String 中的所有字符转换为大写
- String trim(): 返回字符串的副本, 忽略前导空白和尾部空白
- boolean equals(Object obj): 比较字符串的内容是否相同
- boolean equalsIgnoreCase(String anotherString): 与equals方法类似, 忽略大小写
- String concat(String str): 将指定字符串连接到此字符串的结尾。 等价于用“+”
- int compareTo(String anotherString): 比较两个字符串的大小
- String substring(int beginIndex): 返回一个新的字符串, 它是此字符串的从beginIndex开始截取到最后的一个子字符串。
- String substring(int beginIndex, int endIndex) : 返回一个新字符串, 它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
- boolean contains(CharSequence s): 当且仅当此字符串包含指定的 char 值序列时,返回 true
- int indexOf(String str): 返回指定子字符串在此字符串中第一次出现处的索引
- int indexOf(String str, int fromIndex): 返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
- int lastIndexOf(String str): 返回指定子字符串在此字符串中最右边出现处的索引
- int lastIndexOf(String str, int fromIndex): 返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索注: indexOf和lastIndexOf方法如果未找到都是返回-1
- boolean endsWith(String suffix): 测试此字符串是否以指定的后缀结束
- boolean startsWith(String prefix): 测试此字符串是否以指定的前缀开始
- boolean startsWith(String prefix, int toffset): 测试此字符串从指定索引开始的子字符串是否以指定前缀开始
- String replace(char oldChar, char newChar): 返回一个新的字符串, 它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
- String replace(CharSequence target, CharSequence replacement): 使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
- String replaceAll(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement) : 使 用 给 定 的replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- boolean matches(String regex): 告知此字符串是否匹配给定的正则表达式。
- String[] split(String regex): 根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit): 根据匹配给定的正则表达式来拆分此字符串, 最多不超过limit个, 如果超过了, 剩下的全部都放到最后一个元素中。
@Test
public void test4() {
// 定义一个字符串对象
String s = "helloworld";
// int length():获取字符串的长度。
System.out.println("s.length:" + s.length());
System.out.println("----------------------");
// char charAt(int index):获取指定索引位置的字符
System.out.println("charAt:" + s.charAt(0));
System.out.println("----------------------");
// int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l'));
System.out.println("----------------------");
// int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf("owo"));
System.out.println("----------------------");
// int indexOf(int ch,int fromIndex):返回指定字符在此字符串中从指定位置后第一次出现处的索引。
System.out.println("indexOf:" + s.indexOf('l', 4));
System.out.println("indexOf:" + s.indexOf('k', 4)); // -1
System.out.println("indexOf:" + s.indexOf('l', 40)); // -1
System.out.println("----------------------");
// 自己练习:int indexOf(String str,int
// fromIndex):返回指定字符串在此字符串中从指定位置后第一次出现处的索引。
// String substring(int start):从指定位置开始截取字符串,默认到末尾。包含start这个索引
System.out.println("substring:" + s.substring(5));
System.out.println("substring:" + s.substring(5,7)); //开始时5,结束是7,不包括7
System.out.println("substring:" + s.substring(0));
System.out.println("----------------------");
// String substring(int start,int
// end):从指定位置开始到指定位置结束截取字符串。包括start索引但是不包end索引
System.out.println("substring:" + s.substring(3, 8));
System.out.println("substring:" + s.substring(0, s.length()));
String s3 = " abc 123 ";
System.out.println(s3.trim().length()); //去掉前后两端的空格
String s4 = "a,b,c,d,e,123";
String[] s5 = s4.split(",");
for (int i = 0; i < s5.length; i++) {
System.out.println(s5[i]);
}
}
2. StringBuffer和StringBuilder
对字符串进行修改的时候,需要使用这两个类。这两个类的对象能够被多次修改,并且不产生新的对象。
StringBuilder
:是非线程安全的,适用于单线程环境。由于不需要处理线程同步,相比于StringBuffer
,它的性能更高。StringBuffer
:是线程安全的,适用于多线程环境。它包含了一些线程同步的机制,确保在多个线程同时访问时数据的一致性。
除了线程安全性之外,这两个类的功能几乎完全相同。它们都提供了类似的方法来修改和操作字符串,例如追加、插入、删除等操作。你可以根据具体的需求选择使用 StringBuilder
还是 StringBuffer
。如果你的代码在单线程环境下运行,并且对性能有较高要求,那么 StringBuilder
是一个不错的选择。而如果你的代码在多线程环境下运行,或者需要保证数据的线程安全性,那么推荐使用 StringBuffer
。
2.1 StringBuilder
在使用 StringBuffer 类时,每次都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,所以如果需要对字符串进行修改推荐使用 StringBuffer。StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。
public class RunoobTest{
public static void main(String args[]){
StringBuilder sb = new StringBuilder(10);
sb.append("Runoob..");
System.out.println(sb);
sb.append("!");
System.out.println(sb);
sb.insert(8, "Java");
System.out.println(sb);
sb.delete(5,8);
System.out.println(sb);
}
}
运行结果
Runoob..
Runoob..!
Runoob..Java!
RunooJava!
2.2 StringBuffer
当被要求必须要线程安全的情况下,就必须使用StringBuffer类。
public class Test{
public static void main(String args[]){
StringBuffer sBuffer = new StringBuffer("菜鸟教程官网:");
sBuffer.append("www"); //代表将字符串内容追加到sBuffer中
sBuffer.append(".runoob");
sBuffer.append(".com");
System.out.println(sBuffer);
}
}
运行结果:
菜鸟教程官网:www.runoob.com
方法描述:
1 | public StringBuffer append(String s) 将指定的字符串追加到此字符序列。 |
2 | public StringBuffer reverse() 将此字符序列用其反转形式取代。 |
3 | public delete(int start, int end) 移除此序列的子字符串中的字符。 |
4 | public insert(int offset, int i) 将 int 参数的字符串表示形式插入此序列中。 |
5 | insert(int offset, String str) 将 str 参数的字符串插入此序列中。 |
6 | replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字符串中的字符。 |
下边是StringBuffer的其他常用方法:
序号 | 方法描述 |
---|---|
1 | int capacity() 返回当前容量。 |
2 | char charAt(int index) 返回此序列中指定索引处的 char 值。 |
3 | void ensureCapacity(int minimumCapacity) 确保容量至少等于指定的最小值。 |
4 | void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此序列复制到目标字符数组 dst 。 |
5 | int indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。 |
6 | int indexOf(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指定子字符串在该字符串中的索引。 |
7 | int lastIndexOf(String str) 返回最右边出现的指定子字符串在此字符串中的索引。 |
8 | int lastIndexOf(String str, int fromIndex) 返回 String 对象中子字符串最后出现的位置。 |
9 | int length() 返回长度(字符数)。 |
10 | void setCharAt(int index, char ch) 将给定索引处的字符设置为 ch 。 |
11 | void setLength(int newLength) 设置字符序列的长度。 |
12 | CharSequence subSequence(int start, int end) 返回一个新的字符序列,该字符序列是此序列的子序列。 |
13 | String substring(int start) 返回一个新的 String ,它包含此字符序列当前所包含的字符子序列。 |
14 | String substring(int start, int end) 返回一个新的 String ,它包含此序列当前所包含的字符子序列。 |
15 | String toString() 返回此序列中数据的字符串表示形式。 |
2.3 案例
public class TestDemo {
@Test
public void test1(){
StringBuffer sb = new StringBuffer(); //适用于多线程,是线程安全的
sb.append("Hello");
sb.append("Java").append("Python").append("NB");
System.out.println(sb);
}
@Test
public void test2(){
String text = "";
long t1 = System.currentTimeMillis();//获取时间戳,1970-1.1.1.0.0.0到现在的秒
for (int i = 0; i < 20000; i++) {
text=text+i;
}
long t2 = System.currentTimeMillis();//获取时间戳
System.out.println(t2 - t1);
}//测试拼接2两万次字符串耗时
@Test
public void test3(){
StringBuffer sb1 = new StringBuffer(); //需要同步,适用多线程
long t1 = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
sb1.append(i);
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
@Test
public void test4(){
StringBuilder sb2 = new StringBuilder(); //不需要同步,使用单线程
long t1 = System.currentTimeMillis();
for (int i = 0; i < 20000; i++) {
sb2.append(i);
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
}
3. 日期时间类
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。
3.1 传统日期时间处理
1. System.out.println(System.currentTimeMillis()); 获取时间戳:格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
3.2 Date
表示特定的瞬间,精确到毫秒,注意这个类包括上下文(时区)
- 构造器:
-
- Date(): 使用无参构造器创建的对象可以获取本地当前时间。
- Date(long date)
- 常用方法
-
- getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。
- toString():把此 Date 对象转换为以下形式的 String: dow mon dd hh:mm:ss zzz yyyy 其中: dow 是一周中的某一天 (Sun, Mon, Tue,Wed, Thu, Fri, Sat), zzz是时间标准。
代码:
public class Demo1 {
@Test
public void test1() {
System.out.println(System.currentTimeMillis());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss.SSS");
Date date = new Date();
System.out.println(sdf.format(date));
System.out.println(date.getTime());//得到时间戳
Date date1 = new Date(1);
System.out.println(sdf.format(date1));
}
}
3.3 SimpleDateFormat
SimpleDateFormat
是 Java 中用于格式化和解析日期时间的类(类似于时间规范)。它位于 java.text
包中,提供了许多模式字符来定义日期时间的格式。它允许进行格式化:日期 -> 文本、 解析:文本 -> 日期。以下是一些常用的模式字符,你可以使用这些模式字符按照需要组合成日期时间格式字符串,并将其作为参数传递给 SimpleDateFormat
的构造函数:
y
:年份(例如:2023)M
:月份(例如:8或08)d
:日期(例如:31或01)H
:24小时制的小时(例如:13或03)h
:12小时制的小时(例如:1或01)m
:分钟(例如:49或09)s
:秒(例如:25或05)S
:毫秒(例如:396)E
:星期几的简写(例如:Mon)EEE
:星期几的完整名称(例如:Monday)a
:上午/下午标记(例如:AM/PM)
3.3.1 代码使用:
@Test
public void DemoText() throws ParseException {
Date date = new Date();
System.out.println(date);
//设置时间显示格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
System.out.println(sdf.format(date));
String dateStr = "1970-01-1 08:0:0.0";
Date date2 = sdf.parse(dateStr); //字符串转换为时间类型
System.out.println(date2.getTime());//获取指定时间的时间戳
System.out.println(sdf.format(date2));
System.out.println(date2);//打印指定时间
}
3.4 Calendar
Calendar
是 Java 中用于处理日期和时间的类,在 Java 8 之前是主要的日期和时间 API。它提供了许多方法来操作日期、时间和日历字段,包括获取、设置、计算和比较等操作。它提供了许多用于操作日期和时间的方法。使用 Calendar
需要先通过调用 getInstance()
方法获取一个Calendar
对象的实例。然后,你可以使用该对象来获取当前日期和时间,或者进行日期和时间的计算和操作。
3.4.1 方法
获取日期和时间信息:
get(Calendar.FIELD)
:获取给定日历字段的值,如Calendar.YEAR
获取年份,Calendar.MONTH
获取月份(需要加 1),Calendar.DAY_OF_MONTH
获取月中的天数等。getActualMaximum(Calendar.FIELD)
:获取给定日历字段在当前日历中的最大值,如Calendar.DAY_OF_MONTH
获取月中最大的天数。设置日期和时间信息:
set(Calendar.FIELD, value)
:设置给定日历字段的值,如Calendar.YEAR
设置年份,Calendar.MONTH
设置月份(需要减 1),Calendar.DAY_OF_MONTH
设置月中的天数等。计算日期和时间:
add(Calendar.FIELD, amount)
:根据给定的日历字段和偏移量,将日期增加或减少指定的数量,如Calendar.YEAR
增加或减少年份,Calendar.MONTH
增加或减少月份,Calendar.DAY_OF_MONTH
增加或减少天数等。比较日期和时间:
compareTo(Calendar anotherCalendar)
:比较两个Calendar
对象表示的日期和时间,返回一个负整数、零或正整数,表示当前Calendar
对象早于、等于或晚于另一个Calendar
对象。注意:
Calendar
类的月份是从 0 开始计数的,即 0 表示一月,11 表示十二月。所以在使用get(Calendar.MONTH)
方法获取月份时需要加 1,而在使用set(Calendar.MONTH, value)
方法设置月份时需要减 1。
3.4.2 代码案例:
public class Demo1 {
@Test
public void Demo1() throws ParseException {
//初始化时间格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//先获取Calander实例
Calendar c = Calendar.getInstance();//当前时间
System.out.println(sdf.format(c.getTime())); //用sdf实例打印当前时间
// 得到field
System.out.println(c.get(Calendar.YEAR));//得到年
System.out.println(c.get(Calendar.MONTH));//得到月
System.out.println(c.get(Calendar.DAY_OF_MONTH));//得到日
System.out.println(c.get(Calendar.HOUR_OF_DAY));//得到小时
//设置filed
c.set(Calendar.MONTH,1);//传统日期0开始,1为2月
System.out.println(sdf.format(c.getTime()));
//减3个月
c.add(Calendar.MONTH, -3);
System.out.println(sdf.format(c.getTime()));//得到date
String datestr = "1970-01-1 08:0:0.0";
Date date = sdf.parse(datestr); //转换为Date
System.out.println(date.getTime());
Calendar c2 = Calendar.getInstance();
c2.set(1970,0,1,8,0,0);
System.out.println(sdf.format(c2.getTime())+" = 方式2设置时间");
//当前时间4周后
Calendar c3 = Calendar.getInstance();
c3.add(Calendar.WEEK_OF_YEAR,5);
System.out.println(sdf.format(c3.getTime())+" = 当前时间4周后");
}
}
3.5 JDK8新日期API
在 JDK 8 中引入了新的日期和时间 API,即 java.time
包。这个新的 API 提供了一组强大、易用且线程安全的类,用于处理日期、时间、时间间隔、时区和时刻等。
以下是 JDK 8 新日期 API 的一些关键类:
LocalDate
:表示一个日期(年、月、日)的类。LocalTime
:表示一个时间(小时、分钟、秒和纳秒)的类。LocalDateTime
:表示一个日期和时间的类,包括年、月、日、小时、分钟、秒和纳秒。ZonedDateTime
:表示带有时区的日期和时间。Period
:表示两个日期之间的时间间隔。Duration
:表示两个时刻之间的时间间隔。
这些类提供了一系列方法来操作日期和时间,例如创建、修改、比较、格式化和解析等。
3.5.1 LocalDateTime、LocalDate、LocalTime
LocalDate、 LocalTime、 LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
LocalDate
表示一个日期(年、月、日)的类。它是不可变的,可以用于存储和操作日期信息。例如,你可以使用 LocalDate.of()
方法创建指定年月日的日期对象,也可以使用 LocalDate.now()
方法获取当前日期。
LocalTime time = LocalTime.of(12, 30, 0); // 创建指定时间对象
LocalTime now = LocalTime.now(); // 获取当前时间
int hour = time.getHour(); // 获取小时
int minute = time.getMinute(); // 获取分钟
int second = time.getSecond(); // 获取秒数
System.out.println("指定时间:" + time);
System.out.println("当前时间:" + now);
System.out.println("小时:" + hour);
System.out.println("分钟:" + minute);
System.out.println("秒数:" + second);
LocalTime
表示一个时间(小时、分钟、秒和纳秒)的类。它也是不可变的,用于存储和操作时间信息。你可以使用 LocalTime.of()
方法创建指定时分秒的时间对象,也可以使用 LocalTime.now()
方法获取当前时间。
LocalTime time = LocalTime.of(12, 30, 0); // 创建指定时间对象
LocalTime now = LocalTime.now(); // 获取当前时间
int hour = time.getHour(); // 获取小时
int minute = time.getMinute(); // 获取分钟
int second = time.getSecond(); // 获取秒数
System.out.println("指定时间:" + time);
System.out.println("当前时间:" + now);
System.out.println("小时:" + hour);
System.out.println("分钟:" + minute);
System.out.println("秒数:" + second);
LocalDateTime
组合了日期和时间,表示一个完整的日期时间(年、月、日、小时、分钟、秒和纳秒)。你可以使用 LocalDateTime.of()
方法创建指定日期时间的对象,也可以使用 LocalDateTime.now()
方法获取当前日期时间。
LocalDateTime dateTime = LocalDateTime.of(2023, 9, 1, 12, 30, 0); // 创建指定日期时间对象
LocalDateTime now = LocalDateTime.now(); // 获取当前日期时间
int year = dateTime.getYear(); // 获取年份
Month month = dateTime.getMonth(); // 获取月份
int dayOfMonth = dateTime.getDayOfMonth(); // 获取日期
int hour = dateTime.getHour(); // 获取小时
int minute = dateTime.getMinute(); // 获取分钟
int second = dateTime.getSecond(); // 获取秒数
System.out.println("指定日期时间:" + dateTime);
System.out.println("当前日期时间:" + now);
System.out.println("年份:" + year);
System.out.println("月份:" + month);
System.out.println("日期:" + dayOfMonth);
System.out.println("小时:" + hour);
System.out.println("分钟:" + minute);
System.out.println("秒数:" + second);
3.5.2 Instant
Instant
是 Java 8 中的一个类,用于表示时间戳(Timestamp)。它是不可变的,并且以距离 "epoch"(1970-01-01T00:00:00Z)的秒数为基础来存储时间信息。
- 处理时间和日期的时候,我们通常会想到年,月,日,时,分,秒。然而,这只是时间的一个模型,是面向人类的。第二种通用模型是面向机器的,或者说是连续的。在此模型中,时间线中的一个点表示为一个很大的数,这有利于计算机处理。 在UNIX中,这个数从1970年开始,以秒为的单位;同样的,在Java中,也是从1970年开始,但以毫秒为单位。
- java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。 Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲, 它只是简单的表示自1970年1月1日0时0分0秒( UTC)开始的秒数。 因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。
- (1 ns = 10-9 s) 1秒 = 1000毫秒 =10^6微秒=10^9纳秒
时间戳:时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数
3.5.2(方法)
方法 | 描述 |
---|---|
now() | 获取当前的时间戳。 |
ofEpochSecond(long epochSecond) | 根据指定的秒数创建时间戳。 |
ofEpochMilli(long epochMilli) | 根据指定的毫秒数创建时间戳。 |
getEpochSecond() | 获取时间戳的秒数。 |
toEpochMilli() | 获取时间戳的毫秒数。 |
plusSeconds(long secondsToAdd) | 在时间戳上添加指定的秒数。 |
plusMillis(long millisToAdd) | 在时间戳上添加指定的毫秒数。 |
plusNanos(long nanosToAdd) | 在时间戳上添加指定的纳秒数。 |
minusSeconds(long secondsToSubtract) | 从时间戳中减去指定的秒数。 |
minusMillis(long millisToSubtract) | 从时间戳中减去指定的毫秒数。 |
minusNanos(long nanosToSubtract) | 从时间戳中减去指定的纳秒数。 |
isAfter(Instant otherInstant) | 比较两个时间戳的先后顺序,判断当前时间戳是否在指定时间戳之后。 |
isBefore(Instant otherInstant) | 比较两个时间戳的先后顺序,判断当前时间戳是否在指定时间戳之前。 |
3.5.3 DateTimeFormatter(日期时间格式化类)
DateTimeFormatter
是 Java 8 中提供的一个日期时间格式化类,它可以将日期时间对象格式化为指定的字符串,也可以将指定的字符串解析为日期时间对象。以下是 DateTimeFormatter
的常用方法:
ofPattern()
:创建一个日期时间格式化器。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//创建一个日期时间格式化器
format()
:将日期时间对象格式化为字符串。
LocalDateTime dateTime = LocalDateTime.now();
String formattedDate = formatter.format(dateTime);
//将日期时间格式化为字符串
parse()
:将字符串解析为日期时间对象。
String strDate = "2021-09-20 16:30:00";
LocalDateTime parsedDate = LocalDateTime.parse(strDate, formatter);
//字符串解析为日期时间对象
withLocale()
:设置日期时间格式化器的本地化。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withLocale(Locale.ENGLISH);
//设置日期时间格式化器的本地化
withZone()
:设置日期时间格式化器的时区。
ZoneId zoneId = ZoneId.of("Asia/Shanghai");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(zoneId);
withResolverStyle()
:设置日期时间解析器的解析风格。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd").withResolverStyle(ResolverStyle.STRICT);
3.5.4 与传统日期类转换练习
@Test
public void test1(){
LocalDateTime l1 = LocalDateTime.now();
System.out.println("当前时间:"+l1);
System.out.println(l1.getMonth().getValue());//新时间api,月从1开始
System.out.println(l1.getYear()); //得到年份
System.out.println(l1.get(ChronoField.HOUR_OF_AMPM)); //时间
//设置filed 新日期从1开始
LocalDateTime l2 = l1.withMonth(1).withDayOfMonth(2);
System.out.println(l2);
//加3个月 3周
LocalDateTime l3 = l2.plusMonths(3).plusWeeks(3);
System.out.println(l3);
//减三个月 1周
LocalDateTime l4 = l3.plusMonths(-3).plusWeeks(1);
System.out.println(l4);
//创建1970-1-1 8:0:0.0时间
LocalDateTime l5 = LocalDateTime.of(1970, 1, 1, 0, 0, 0, 0);
System.out.println(l5);
//时间戳操作 Instant
Instant i1 = l5.toInstant(ZoneOffset.UTC); //得到utc时间的Instant
System.out.println(i1.toEpochMilli());
// ZoneOffset.getAvailableZoneIds().forEach(s -> System.out.println(s));
LocalDateTime l6 = LocalDateTime.of(1970, 1, 1, 8, 0, 0, 0);
Instant i2 = l6.toInstant(ZoneOffset.ofHours(8)); //得到东8区的Instant
System.out.println(i2.toEpochMilli()); //utc时间的1970.1.1.0点,北京时间的8点,是时间戳的0
//格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日HH时mm分ss秒.SSS");
System.out.println(formatter.format(LocalDateTime.now()));
// formatter.parse() //转化(解析一个时间)
4. System 和 Runtime类
4.1 System类
- System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
- 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的, 所以也可以很方便的进行调用。
- 成员变量
- System类内部包含in、 out和err三个成员变量,分别代表标准输入流(键盘输入),标准输出流(显示器)和标准错误输出流(显示器)。
- 成员方法:
- native long currentTimeMillis():该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
- void exit(int status):该方法的作用是退出程序。其中status的值为0代表正常退出,非零代表异常退出。 使用该方法可以在图形界面编程中实现程序的退出功能等。
- void gc():该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
- String getProperty(String key):该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
public static void main(String[] args) {
Scanner s1 = new Scanner(System.in);
System.out.println("输入1,输入0退出");
int i = s1.nextInt();
if (i == 0) {
System.out.println("系统退出");
System.exit(0);//退出
}
System.out.println("i = "+i);
}
@Test
public void test2(){
System.out.println(System.currentTimeMillis()); //获取时间戳
}
@Test
public void test3(){
String javaVersion = System.getProperty("java.version");
System.out.println(javaVersion);// 获取JDK版本
String javaHome = System.getProperty("java.home");
System.out.println(javaHome);// 获取JDK安装目录
String osName = System.getProperty("os.name");
System.out.println("os的name:" + osName); //获取操作系统名称
String osVersion = System.getProperty("os.version");
System.out.println("os的version:" + osVersion);// 获取操作系统版本
String userName = System.getProperty("user.name");
System.out.println("user的name:" + userName);// 获取管理员名称
String userHome = System.getProperty("user.home");
System.out.println("user的home:" + userHome);//获取管理员目录
String userDir = System.getProperty("user.dir");
System.out.println("user的dir:" + userDir);//获取工程目录
}
4.2 Runtime类
Runtime
类是 Java 中用于与运行时环境进行交互的类。它提供了许多与 Java 虚拟机(JVM)相关的方法,可以执行系统级操作,例如执行外部程序、获取处理器数量和内存信息等。
以下是 Runtime
类的一些常见方法:
getRuntime()
:返回当前运行时的 Runtime 对象。
Runtime runtime = Runtime.getRuntime();
exec(String command)
:在单独的进程中执行指定的命令。
Process process = runtime.exec("ls -l");
availableProcessors()
:返回可用的处理器数量。
int processors = runtime.availableProcessors();
totalMemory()
:返回 Java 虚拟机的总内存量。
long totalMemory = runtime.totalMemory();
freeMemory()
:返回 Java 虚拟机的空闲内存量。
long freeMemory = runtime.freeMemory();
gc()
:运行垃圾回收器。
runtime.gc();
Runtime
类还提供了其他一些方法,用于执行系统级操作,如加载动态链接库、设置安全管理器等。需要注意的是,Runtime
类的构造函数是私有的,因此不能使用 new
关键字创建实例,而是使用 getRuntime()
方法获取当前运行时的对象。请注意,在使用 Runtime
类执行外部命令时需要小心,确保提供的命令是可靠和安全的,以避免潜在的安全风险。
public class RuntimeDemo {
public static void main(String[] args) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("捕获了jvm退出--释放资源");
}
}));
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("123");
// int i = 1 / 0;
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("123");
System.out.println("abc");
System.out.println("-------------------");
//main执行完毕,钩子被触发,打印语句。
}
}
执行结果:
4.2.1 钩子(HOOK)
在计算机编程中,钩子(Hook)是一种机制,允许程序在特定事件发生时插入自定义代码或函数。这些事件可以是系统级事件、应用程序事件或者其他特定的软件事件。
钩子可用于修改或扩展程序的行为,使其能够响应或捕获特定事件,并执行相应的操作。通过使用钩子,程序可以截获和处理事件,而不需要修改原始代码。
钩子可以分为两种类型:
-
系统级钩子(System-level Hooks):这种钩子可以截获操作系统级别的事件,例如鼠标点击、键盘输入、窗口消息等。它们通常用于监视或修改系统行为,实现全局的事件拦截和处理。
-
应用程序级钩子(Application-level Hooks):这种钩子在应用程序内部使用,用于截获特定的应用程序事件。它们通常用于在应用程序内部添加自定义逻辑,以实现特定的功能或扩展应用程序的行为。
钩子在很多场景中都有广泛应用,例如:实现日志记录、性能监控、自动化测试、安全审计等。需要注意的是,在使用钩子时,应谨慎处理,并确保钩子代码的正确性和稳定性,以避免潜在的错误和安全风险。
5. BigInteger和BigDecimal
5.1 BigInteger
- Integer类作为int的包装类,能存储的最大整型值为231-1, Long类也是有限的,最大为263-1。 如果要表示再大的整数,不管是基本数据类型还是他们的包装类都无能为力,更不用说进行运算了。
- java.math包的BigInteger可以表示不可变的任意精度的整数。 BigInteger 提供所有 Java 的基本整数操作符的对应物,并提供java.lang.Math 的所有相关方法。另外, BigInteger 还提供以下运算:模算术、 GCD 计算、质数测试、素数生成、位操作以及一些其他操作。
- 常用方法:
-
- public BigInteger abs():返回此 BigInteger 的绝对值的 BigInteger。
- BigInteger add(BigInteger val) :返回其值为 (this + val) 的 BigInteger
- BigInteger subtract(BigInteger val) :返回其值为 (this - val) 的 BigInteger
- BigInteger multiply(BigInteger val) :返回其值为 (this * val) 的 BigInteger
- BigInteger divide(BigInteger val) :返回其值为 (this / val) 的 BigInteger。整数相除只保留整数部分。
- BigInteger remainder(BigInteger val) :返回其值为 (this % val) 的 BigInteger。
- BigInteger[] divideAndRemainder(BigInteger val):返回包含 (this / val) 后跟(this % val) 的两个 BigInteger 的数组。
- BigInteger pow(int exponent) :返回其值为 (thisexponent) 的 BigInteger。
5.2 BigDecimal
一般的Float类和Double类可以用来做科学计算或者工程计算,但在商业计算中,要求数字精度比较高,所以需要用到BigDecimal类
BigDecimal支持不可变的、任意精度的有符号十进制定点数。
- 构造器
-
- public BigDecimal(double val)
- public BigDecimal(String val)
- 常用方法
-
- public BigDecimal add(BigDecimal augend)
- public BigDecimal subtract(BigDecimal subtrahend)
- public BigDecimal multiply(BigDecimal multiplicand)
- public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)
public class BigIntegerTest {
@Test
public void test(){
System.out.println(Integer.MAX_VALUE);
Integer i1 = 2147483647;
BigInteger i3 = new BigInteger("10");
System.out.println(i3);
BigInteger i4 = new BigInteger("15");
BigInteger i5 = i3.add(i4);
System.out.println(i5);
// i3/3的余数和商
BigInteger[] arrs = i3.divideAndRemainder(new BigInteger("3"));
System.out.println(Arrays.toString(arrs));
}
}