1、String
1.1、String的特性
String类: 代表字符串
。Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。- String是一个final类,代表
不可变的字符序列
。 - 字符串是常量,用双引号引起来表示。它们的值在创建之后不能更改。
- String对象的字符内存是存储在一个字符数组value[]中的。
1.1、String的概述
String:字符串,使用一对""引起来表示
-
String声明为final的,不可被继承。
-
String实现了Serializable接口: 表示字符串是支持序列化的。
-
String实现了Comparable接口: 表示String可以比较大小。
-
String内部定义了final char[] value用于存储字符串数据
-
String: 代表不可变的字符序列。简称: 不可变性。
-
@Test public void test1(){ String s1 = "abc";//字面量的定义方式 String s2 = "abc"; System.out.println(s1);//abc System.out.println(s2);//abc }
-
通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中。
-
字符串常量池中是不会存储相同内容的字符串的
-
-
当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
-
@Test public void test1(){ String s1 = "abc";//字面量的定义方式 String s2 = "abc"; s1 = "hello" System.out.println(s1);//hello System.out.println(s2);//abc }
-
-
当对现有的字符串进行连接操作时,也需要重新指定内存区域值,不能使用原有的value上赋值。
-
@Test public void test1(){ String s1 = "abc";//字面量的定义方式 String s2 = "abc"; s1 = "hello"; System.out.println(s1);//hello System.out.println(s2);//abc String s3 = "edf"; s3 +=s2; System.out.println(s3); }
-
-
当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域值,不能使用原有的value进行赋值。
-
@Test public void test1(){ String s1 = "abc";//字面量的定义方式 String s2 = s1.replace("a", "m"); System.out.println(s1);//abc System.out.println(s2);//mbc }
-
1.2、String实例化方式
方式一: 通过字面量定义的方式
// 通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中
String s1 = "javaEE";
String s2 = "javaEE";
方式二: 通过new + 构造器方式
// 通过new + 构造器的方式: 此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以及对应的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");
1.3、字符串拼接方式赋值对比
说明
- 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
- 只要其中一个是变量,结果就在堆中。
- 如果拼接的结果调用intern()方法,返回值就在常量池中
代码示例
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4);//true
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//false
System.out.println(s5 == s6);//false
System.out.println(s5 == s7);//false
System.out.println(s6 == s7);//false
String s8 = s6.intern();//返回值得到的s8使用的常量值中已经存在的“javaEEhadoop”
System.out.println(s3 == s8);//true
****************************
String s1 = "javaEEhadoop";
String s2 = "javaEE";
String s3 = s2 + "hadoop";
System.out.println(s1 == s3);//false
final String s4 = "javaEE";//s4:常量
String s5 = s4 + "hadoop";
System.out.println(s1 == s5);//true
内存解析
2、String类常用方法
//操作字符:
int 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 endsWith(String suffix):测试此字符串是否以指定的后缀结束
boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
//查找字符串中的字符
//注:indexOf和lastIndexOf方法如果未找到都是返回-1
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):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
//替换
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 test3(){
//1.int length():返回字符串的长度: return value.length
String s1 = "what are you doing?";
System.out.println(s1.length());//19
//2.char charAt(int index): 返回某索引处的字符return value[index]
String s2 = "china";
System.out.println(s2.charAt(1));//h
//3.boolean isEmpty():判断是否是空字符串:return value.length == 0
String s3 = "a";
System.out.println(s3.isEmpty());//false
//4.String toLowerCase():使用默认语言环境,将 String 中的所字符转换为小写
String s4 = "MY NAME IS YE KONG ZHONG ZUI LIANG DE XING";
System.out.println(s4.toLowerCase());//my name is ye kong zhong zui liang de xing
//5.String toUpperCase():使用默认语言环境,将 String 中的所字符转换为大写
String s5 = "my name is ye kong zhong zui liang de xing";
System.out.println(s5.toUpperCase());//MY NAME IS YE KONG ZHONG ZUI LIANG DE XING
//6.String trim():返回字符串的副本,忽略前导空白和尾部空白,取出收尾空格
String s6 = " Hello Ch ina ";
String s7 = s6.trim();
System.out.println("----" + s6 + "----");//没去除之前---- Hello Ch ina ----
System.out.println("----" + s7 + "----");//去除之后----Hello Ch ina----
//7.boolean equals(Object obj):比较字符串的内容是否相同
String s8 = "张三";
String s9 = "张三";
System.out.println(s8.equals(s9));//true
//8.boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
String s10 = "hello";
String s11 = "Hello";
System.out.println(s10.equals(s11));//false 由此可见equals比较的内容是区分大小写的
System.out.println(s10.equalsIgnoreCase(s11));//true 忽略大小写
//9.String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
String s12 = "李四";
String s13 = "我是";
System.out.println(s13.concat(s12));//我是李四
//10.int compareTo(String anotherString):比较两个字符串的大小
String s14 = "125";
String s15 = "123";
System.out.println(s14.compareTo(s15));//2
//源码
/*
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
*/
//11.String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
String s16 = "My home is china";
System.out.println(s16.substring(3));//home is china
//12.String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
String s17 = "hello china";
System.out.println(s17.substring(6,11));//china endIndex不包含进去
//13.boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
String s18 = "Hello zhangsan";
System.out.println(s18.endsWith("san"));//true
//14.boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
String s19 = "china";
System.out.println(s19.startsWith("ch"));//true
//15.boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
String s20 = "Hello";
System.out.println(s20.startsWith("e",1));
//16.boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
String s21 = " Hello china";
String s22 = "china";
System.out.println(s21.contains(s22));//s21是否包含s22 true
//17.int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
String s23 = "ye kong zhong zui liang de xing";
System.out.println(s23.indexOf("k"));//3
//18.int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
String s24 = "ye kong zhong zui liang de xing";
System.out.println(s24.indexOf("z",3));//8
//19.int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
String s25 = "ye kong zhong zui liang de xing";
System.out.println(s25.lastIndexOf("d"));//24
//20.int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
String s26 = "ye kong zhong zui liang de xing";
System.out.println(s26.lastIndexOf("k",4));//3
//21.String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所 oldChar 得到的。
String s27 = "hello";
String s28 = s27.replace("h","c");
System.out.println(s28);//cello
//22.String replace(CharSequence target,CharSequence replacement):使用指定的字面值替换序列替换此字符串所匹配字面值目标序列的子字符串。
String s29 = "北京天气真好";
String s30 = s29.replace("北京","上海");
System.out.println(s30);//上海天气真好
//23.String replaceAll(String regex, String replacement):使用给定的 replacement 替换此字符串所匹配给定的正则表达式的子字符串。
String str = "12hello34world5java7891mysql456";
//把字符串中的数字替换成,,如果结果中开头和结尾有,的话去掉
String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");
System.out.println(string);//hello,world,java,mysql
//24.boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。
str = "12345";
//判断str字符串中是否全部有数字组成,即有1-n个数字组成
boolean matches = str.matches("\\d+");
System.out.println(matches);//true
String tel = "0571-4534289";
//判断这是否是一个杭州的固定电话
boolean result = tel.matches("0571-\\d{7,8}");
System.out.println(result);//true
//25.String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。
str = "hello|world|java";
String[] strs = str.split("\\|");
for (int i = 0; i < strs.length; i++) {
System.out.println(strs[i]);//依次输出hello word java
}
//26.String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
str = "hello.world.java";
String[] strs2 = str.split("\\.",3);
for (int i = 0; i < strs2.length; i++) {
System.out.println(strs2[i]);//依次输出hello word java
}
}
3、转换
3.1、String与字符数组之间的转换
String ----> char[]:调用String的toCharArray();
@Test
public void test4(){
String str = "15sadaw";
char[] c1 = str.toCharArray();
for (int i = 0; i <c1.length ; i++) {
System.out.println(c1[i]);
}
}
char[] —> String : 调用String的构造器
@Test
public void test2(){
char[] c2 = new char[]{'s','1','a','7','z'};
String string = new String(c2);
System.out.println(c2);
}
3.2、String与与字节数组之间的转换
String —> byte[]: 调用String的getBytes()
@Test
public void test3(){
String str = "sada";
byte[] bytes = str.getBytes();
System.out.println(Arrays.toString(bytes));
}
byte[] —>String: 调用String的构造器
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码。
3.2、String与StringBuffer、StringBuilder之间的转换
String、StringBuffer、StringBuilder三者的异同?
String
: 不可变的字符序列;底层使用char[]存储;
StringBuffer
: 可变的字符序列;线程安全的,效率低;底层使用char[]存储;
StringBuilder
: 可变的字符序列; jdk5.0新增的,线程不安全的,效率高;底层使用char[]存储;
StringBuffer与StringBuilder的常用方法
StringBuffer append(xxx): 提供了很多的append()方法,用于进行字符串拼接
StringBuffer delete(int start,int end): 删除指定位置的内容
StringBuffer replace(int start,int end, String str): 把[start,end]位置替换为str
StringBuffer insert(int offset,xxx): 在指定位置插入xxx
StringBuffer reverse(): 把当前字符序列逆转;反转颠倒;
public int indexOf(String str):返回字符串在当前StringBuffer指定出现的位置
public String substring(int start,int end):返回一个从start开始到end索引结束的左闭右开区间的子字符串
public int length():获取当前字符串的长度
public char charAt(int n): 通过下标索引获取字符
public void setCharAt(int n,char ch) :通过下标索引修改指定字符
//代码示例
@Test
public void test(){
StringBuffer buffer = new StringBuffer("abc");
buffer.append("def");
System.out.println(buffer);
System.out.println("***********");
buffer.delete(1,3);
System.out.println(buffer);
System.out.println("***********");
buffer.replace(0,2,"ccc");
System.out.println(buffer);
System.out.println("***********");
buffer.insert(0,"a");
System.out.println(buffer);
System.out.println("***********");
buffer.reverse();
System.out.println(buffer);
System.out.println("***********");
int a = buffer.indexOf("e");
System.out.println(a);
System.out.println("***********");
String substring = buffer.substring(0, 4);
System.out.println(substring);
System.out.println("***********");
int length = buffer.length();
System.out.println(length);
System.out.println("***********");
char c = buffer.charAt(0);
System.out.println(c);
System.out.println("***********");
buffer.setCharAt(0,'a');
System.out.println(buffer);
}
String -->StringBuffer、StringBuilder: 调用StringBuffer、StringBuilder构造器
@Test
public void StringToStringBufferTest(){
String str1 ="helloword";
StringBuffer stringBuffer = new StringBuffer(str1);
System.out.println(stringBuffer);//helloword
StringBuilder stringBuilder = new StringBuilder(str1);
System.out.println(stringBuilder);//helloword
stringBuffer.append("isStringBuffer");
System.out.println(stringBuffer);//hellowordandgood
stringBuilder.append("isStringBuider");
System.out.println(stringBuilder);
}
StringBuffer、StringBuilder -->String:
①调用String构造器; ②StringBuffer、StringBuilder的toString()
@Test
public void StringBuiderOrStringBufferToStringTest() {
StringBuffer sb1 = new StringBuffer("hello StringBuffer");
System.out.println(sb1);
StringBuilder sb2 = new StringBuilder("hello StringBuider");
System.out.println(sb2);
System.out.println("----------------------");
String str1 = new String(sb1);
System.out.println(str1);
String str2 = new String(sb2);
System.out.println(str2);
System.out.println("----------------------");
System.out.println(sb1.toString());
System.out.println(sb2.toString());
}
4、JDK8.0以前的日期时间API
4.1、java.lang.System类
System类提供的public static long currentTimeMillis()用来返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
# 计算世界时间的主要标准有:
UTC(Coordinated Universal Time)
GMT(Greenwich Mean Time)
CST(Central Standard Time)
//示例
@Test
public void test1(){
//获取系统当前时间:System类中的currentTimeMillis()
long time = System.currentTimeMillis();
//返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差。
//称为时间戳
System.out.println(time);
}
4.2、java.util.Date类
表示特定的瞬间,精确到毫秒
java.util.Date类
----子类 java.sql.Date类
1.两个构造器的使用
-
//构造器一: Date(): 创建一个对应当前时间的Date对象
-
//构造器二: 创建指定毫秒数的Date对象
-
//代码示例 //构造器一: Date(): 创建一个对应当前时间的Date对象 Date date = new Date(); System.out.println(date.toString()); System.out.println(date.getTime()); System.out.println("*************"); //构造器二: 创建指定毫秒数的Date对象 Date date1 = new Date(1603180548461L); System.out.println(date1.toString());
2.两个方法的使用
- toString(): 显示当前的年、月、日、时、分、秒
- getTime(): 获取当前Date对象对应的毫秒数。 (时间戳)
3.java.sql.Date对应着数据库中的日期类型的变量
如何将java.util.Date对象转换为java.sql.Date对象
@Test
public void test3(){
Date date = new Date();
java.util.Date date1 = new java.sql.Date(date.getTime());
System.out.println(date1);
}
4.3、java.text.SimpleDateFormat类
Date类的AP不易于国际化,大部分被废弃了, java.text.SimpleDateFormat类是一个不与语言环境有关的方式来格式化和解析日期的具体类。
它允许进行格式化:日期→文本、解析:文本→日期
SimpleDateFormat的使用
SimpleDateFormat对日期Date类的格式化和解析
两个操作:
- 格式化: 日期 —>字符串
- 解析: 格式化的逆过程,字符串 —>日期
SimpleDateFormat的实例化:new+构造器
照指定的方式格式化和解析:调用带参的构造器
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//代码示例
//按照指定的方式格式化和解析,调用带参的构造器
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
// 格式化 日期 --- >字符串
String format1 = dateFormat1.format(new Date());
System.out.println(format1);
String str2 = "2020-10-20 06:31:31";
//解析: 要求字符串必须是符合SimpleDateFormat识别的格式(通过构造器参数体现),否则会抛异常。
//解析 字符串 ---> 日期
Date parse = dateFormat1.parse(str2);
System.out.println(parse);
4.4、java.util.Calendar类:日历类、抽象类
Calendar是一个抽象基类,主用用于完成日期字段之间相互操作的功能。
- 获取 Calenda实例的方法 使用 Calendar.getInstance()方法 调用它的子类 GregorianCalendarl的构造器。
- 一个 Calendar的实例是系统时间的抽象表示,通过 get(int field)方法来取得想要的时间信息。 比如YEAR、MONTH、DAY_OF_WEEK、HOUR_OF_DAY、MINUTE、SECOND
- public void set(int field,int value)
- public void add(int field,int amount)
- public final Date get Time() public final void set Time(Date date)
- 注意 获取月份时:一月是0,二月是1,以此类推,12月是11 获取星期时:周日是1,周二是2,。。。周六是7
Galendar日历类(抽象类)的使用
方式一: 创建其子类(GregorianCalendar)的对象 (了解)
方式二: 调用其静态方法getInstance()(常用)
//代码示例
Calendar calendar = Calendar.getInstance();
//System.out.println(calendar.getClass());
常用的方法
get():获取日期
set():设置日期
add():添加、修改日期
getTime:日历类–>Date
setTime:Date–>日历类
//代码示例
//get():获取日期
int i = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(i);
//set():设置日期
calendar.set(Calendar.DAY_OF_WEEK,5);
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
//add():添加、修改日期
calendar.add(Calendar.DAY_OF_WEEK,2);
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
//getTime:日历类-->Date
Date time = calendar.getTime();
System.out.println(time);
//setTime:Date-->日历类
calendar.setTime(time);
int i1 = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println(i1);
5、JDK8中新日期时间API
5.1、日期时间API的迭代:
第一代:jdk 1.0 Date类
第二代:jdk 1.1 Calendar类,一定程度上替换Date类
第三代:jdk 1.8 提出了新的一套API
5.2、前两代的问题:
可变性:像日期和时间这样的类应该是不可变的。
偏移性:Date中的年份是从1900开始的,而月份都从0开始。
格式化:格式化只对Date用,Calendar则不行。 此外,它们也不是线程安全的;不能处理闰秒等。
Java 8.0中新引入的java.time API:
Java 8.0吸收了Joda-Time的精华,以一个新的开始为Java创建优秀的APl。新的java.time中包含了所有关于本地日期(LocalDate)、本地时间(Localtime)、本地日期时间(LocalDate time)、时区(ZonedDate time)和持续时间(Duration)的类。历史悠久的Date类新增了tolnstant()方法用于把Date转换成新的表示形式。这些新增的本地化时间日期API大大简化了日期时间和本地化的管理。
5.3、 Java 8.0中新的日期时间API涉及的包:
5.4、LocalDate、LocalTime、LocalDateTime的使用
说明
① 分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。
② LocalDateTime相较于LocalDate、LocalTime,使用频率要高
③ 类似于Calendar
常用方法
//代码示例
@Test
public void test1(){
//now()获取当前本地的日期、时间、日期时间
LocalDate now = LocalDate.now();
LocalTime now1 = LocalTime.now();
LocalDateTime now2 = LocalDateTime.now();
System.out.println(now);
System.out.println(now1);
System.out.println(now2);
//of()设置指定的年、月、日、时、分、秒没有偏移量
LocalDateTime of = LocalDateTime.of(2020, 10, 22, 19, 40, 55);
System.out.println(of);
//getXxx();获取属性
System.out.println(now2.getDayOfMonth());
System.out.println(now2.getDayOfWeek());
System.out.println(now2.getDayOfYear());
System.out.println(now2.getMinute());
System.out.println(now2.getSecond());
//体现不可变性
//withXxx():相当于设置属性
LocalDateTime localDateTime = now2.withDayOfMonth(20);
System.out.println(now2);
System.out.println(localDateTime);
//plusXxx():相当与添加属性 不可变性
LocalDateTime localDateTime1 = localDateTime.plusDays(5);
System.out.println(localDateTime1);
//minusXXX():相当于减去属性
LocalDateTime localDateTime2 = localDateTime1.minusDays(15);
System.out.println(localDateTime2);
}
5.5、Instant的使用
说明
① 时间线上的一个瞬时点。 概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC开始的秒数。)
② 类似于 java.util.Date类
常用方法
//代码示例
@Test
public void test3(){
//实例化,获取本初子午线对应的标准时间
Instant instant = Instant.now();
System.out.println(instant);//2020-10-22T12:10:06.104Z
//添加偏移量
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);//2020-10-22T20:10:06.104+08:00
//获取对应的毫秒数
long milli = instant.toEpochMilli();
System.out.println(milli);
//通过指定的毫秒数,获取对应的年、月、日、时、分、秒
Instant instant1 = Instant.ofEpochMilli(1603368752392L);
System.out.println(instant1);
}
5.6、日期时间格式化类:DateTimeFormatter
说明
① 格式化或解析日期、时间
② 类似于SimpleDateFormat
常用方法
三种格式化方式
预定义的标准格式
//方式一: 预定义的标准格式
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
//格式化 日期 --- > 文本
LocalDateTime now = LocalDateTime.now();
String format = formatter.format(now);
System.out.println(format);
//解析 文本 ---> 日期
TemporalAccessor parse = formatter.parse("2020-10-22T20:26:45.407");
System.out.println(parse);
本地化相关的格式
//方式二:本地化相关的格式
DateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
//格式化 日期 --- > 文本
LocalDateTime now1 = LocalDateTime.now();
String format1 = formatter1.format(now1);
System.out.println(format1);//20-10-22 下午8:33
//解析 文本 ---- > 日期
TemporalAccessor parse1 = formatter1.parse("20-10-22 下午8:34");
System.out.println(parse1);//{},ISO resolved to 2020-10-22T20:34
自定义格式
//方式三: 自定义格式
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化 日期 --- > 文本
LocalDateTime now2 = LocalDateTime.now();
String format2 = formatter2.format(now2);
System.out.println(format2);
//解析 文本 ---->日期
TemporalAccessor parse2 = formatter2.parse(format2);
System.out.println(parse2);
5.7、JDK8之前和JDK8中日期、时间相关的类分别有哪些?
6、Java比较器
概述
在Java中经常会设计到对象数组的排序问题,那么就涉及到对象之间的比较问题。
- Java实现对象排序的方式有两种:
自然排序:java.lang.Comparable
定制排序:java.util.Comparator
说明
Java中的对象,正常情况下,只能进行比较: == 或 !=。不能使用> 或 <的,但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小。如何实现? 使用两个接口中的任何一个: Comparable 或 Comparator
6.1、Comparable接口的使用
Comparable接口的使用
- 像String、包装类等实现了Comparable接口,重写了compareTo(obj)方法,给出了比较两个对象大小的方式。
- 像String、包装类重写compareTo()方法以后,进行了从小到大的排列
- 重写compareTo(obj)的规则: 如果当前对象this大于形参对象obj,则返回正整数, 如果当前对象this小于形参对象obj,则返回负整数, 如果当前对象this等于形参对象obj,则返回零。
- 对于自定义类来说,如果需要排序,我们可以让自定义类实现Comparable接口,重写compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
- Comparable的典型实现:(默认都是从小到大排列的) String:按照字符串中字符的Uincode值进行比较 Character:按照字符的 Unicode值来进行比较 数值类型对应的包装类以及 BigInteger、BigDecimal:按照它们对应的数值大小进行比较 Boolean:true对应的包装类实例大于false对应的包装类实例 Date、Time等:后面的日期时间比前面的日期时间大
//代码示例
//自定义的类要排序需要实现Comparable接口,重写compareTo方法
//String、包装类已经实现Comparable接口,重写了compareTo方法
public class Goods implements Comparable{
private String name;
private double price;
//指明商品比较大小的方式:照价格从低到高排序,再照产品名称从高到低排序
@Override
public int compareTo(Object o) {
// System.out.println("**************");
if(o instanceof Goods){
Goods goods = (Goods)o;
//方式一:
if(this.price > goods.price){
return 1;
}else if(this.price < goods.price){
return -1;
}else{
// return 0;
return -this.name.compareTo(goods.name);
}
//方式二:
// return Double.compare(this.price,goods.price);
}
// return 0;
throw new RuntimeException("传入的数据类型不一致!");
}
// getter、setter、toString()、构造器:省略
}
6.2、Comparator接口的使用
Comparator接口的使用
说明
- 背景:
当元素的类型没实现java.lang.Comparable接口而又不方便修改代码,或者实现了java.lang.Comparable接口的排序规则不适合当前的操作,那么可以考虑使用 Comparator 的对象来排序
- 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
- 如果方法返回正整数,则表示o1大于o2;
- 如果返回0,表示相等;
- 返回负整数,表示o1小于o2。
//代码示例
//注意compareTo(String类型)比较大小
@Test
public void test5(){
String[] arr = new String[]{"BB","QQ","AA","CC","RR"};
Arrays.sort(arr, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (o1 instanceof String && o2 instanceof String){
String s1 = (String)o1;
String s2 = (String)o2;
return o1.compareTo(o2);
}else {
throw new RuntimeException("异常被处理");
}
}
});
System.out.println(Arrays.toString(arr));
}
Comparable接口与Comparator的使用对比
- Comparable接口的方式一旦指定,保证Comparable接口实现类的对象在任何位置都可以比较大小。
- Comparator接口属于临时性的比较。
7、常用类
7.1、System类
- System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
- 由于该类的构造器是private的,所以无法创建该类的对象,也就是无法实例化该类。其内部的成员变量和成员方法都是static的,所以也可以很方便的进行调用。
成员方法
native long currentTimeMillis():
该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
void exit(int status)
该方法的作用是退出程序。其中 status的值为0代表正常退出,非零代表异常退出。使用该方法可以在图形界面编程中实现程序的退出功能等
void gc()
该方法的作用是请求系统进行垃圾回收。至于系统是否立刻回收,则取决于系统中垃圾回收算法的实现以及系统执行时的情况。
String getProperty(String key)
该方法的作用是获得系统中属性名为key的属性对应的值。系统中常见的属性名以及属性的作用如下表所示:
//代码示例
String javaVersion = System.getProperty("java.version");
System.out.println("java的version:" + javaVersion);
String javaHome = System.getProperty("java.home");
System.out.println("java的home:" + javaHome);
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);
7.2、Math类
java.lang.Math提供了一系列静态方法用于科学计算。其方法的参数和返回值类型一般为double型。
7.3、BigInteger类
java.math包的BigInteger可以表示不可变的任意精度的整数。
BigInteger提供所有Java的基本整数操作符的对应物,并提供 java.lang.Math的所有相关方法。另外,BigInteger还提供以下运算:模算术、GCD计算、质数测试、素数生成、位操作以及一些其他操作。
构造器: BigInteger(String val):根据字符串构建 BigInteger对象
BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));
7.4、BigDecimal类
要求数字精度比较高,用到java.math.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 rounding Mode)
//代码示例
@Test
public void test2() {
BigInteger bi = new BigInteger("1243324112234324324325235245346567657653");
BigDecimal bd = new BigDecimal("12435.351");
BigDecimal bd2 = new BigDecimal("11");
System.out.println(bi);
// System.out.println(bd.divide(bd2));
System.out.println(bd.divide(bd2, BigDecimal.ROUND_HALF_UP));
System.out.println(bd.divide(bd2, 25, BigDecimal.ROUND_HALF_UP));
}