框架 Spring Boot 技術入門到整合 6-3 thymeleaf 常用標籤的使用方法
常用類
- 字串相關的類
- String類及常用方法
- StringBuffer
- StringBuilder
- JDK8之前的日期時間API
- System靜態方法---------->currentTimeMillis()
- Date類
- Calendar類
- SimpleDateFormat類
- JDK8中新日期時間API
- LocalDate
- LocalTime
- LocalDateTime
- Instant
- DateTimeFormatter
- Java比較器
- Compara介面
- Comparator介面
- System類
- Math類
- BigInteger與BigDecimal
String
-
String類:代表字串
-
String實現了Serializable介面:表示字串是支援序列化的。
實現了Comparable介面:表示String可以比較大小。 -
String內部定義了final char[] value用於儲存字串資料。
-
String:代表不可變的字元序列。簡稱:不可變性。
-
體現:
- 當對字串重新賦值時,需要重寫指定記憶體區域賦值,不能使用原有的value進行賦值。
- 當對現有的字串進行連線操作時,也需要重新指定記憶體區域賦值,不能使用原有的value賦值。
- 當呼叫String的replace()方法修改指定字元或字串時,也需要重新指定記憶體區域賦值。
-
@Test public void test1(){ String s1="abc";//字面量 String s2="abc"; s1="hello"; System.out.println(s1);//hello System.out.println(s2);//abc
-
-
字串是常量,它們的值在建立之後不能更改。
-
String物件的字元內容是儲存在一個字元陣列value[]中的。
-
通過字面量的方式(區別於new)給一個字串賦值,此時的字串值宣告在字串常量池中。
-
字串常量池中是不會儲存相同內容的字串。
String物件的建立
String的例項化方式:
-
通過字面量定義的方式
-
通過new + 構造器的方式
String str = "hello";
//本質上this.value = new char[0];
String s1 = new String();
//this.value = original.value;
String s2 = new String(String original);
//this.value = Arrays.copyOf(value,value.length);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count);
@Test
public void test2(){
//通過字面量定義的方法:此時的s1和s2的資料javaEE宣告在方法區的字串常量池中。
String s1 = "javaEE";
String s2 = "javaEE";
//通過new+構造器的方式:此時的s3和s4儲存的地址值,是資料在堆空間中開闢空間以後對應的地址值
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1==s2);//true
System.out.println(s2==s3);//false
System.out.println(s3==s4);//false
System.out.println(s4==s1);//false
System.out.println("=================");
Person p1 = new Person("Tom",12);
Person p2 = new Person("Tom",12);
System.out.println(p1.name.equals(p2.name));//true
System.out.println(p1.name==p2.name);//true
p1.name = "Jerry";
System.out.println(p2.name);//Tom
}
圖解:
面試題:
- String s = new String("abc");方式建立物件,在記憶體中建立了幾個物件?
- 兩個:一個是在堆空間中new結構,另一個是char[]對應的常量池中的資料:"abc"。
@Test
public void test3(){
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;
String s8 = s5.intern();//返回值得到的s8使用的常量值中已經存在的“javaEEhadoop”
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
System.out.println(s3==s8);//true
}
結論:
- 常量與常量的拼接結果在常量池,且常量池中不會存在相同內容的常量。
- 只要其中有一個變數,結果就在堆中。
- 如果拼接的結果呼叫intern()方法,返回值就在常量池中。
面試題:
public class StringTest {
String str = new String("good");
char[] ch ={'t','e','s','t'};
public void change(String str,char ch[]){
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);//good
System.out.println(ex.ch);//best
}
}
String類常用方法
package stringtest;
import org.junit.jupiter.api.Test;
public class StringMethodTest {
@Test
public void test(){
String s1 = "Hello World";
String s2 = new String(" boom shit ");
String s3 = "Hello World";
String s4 = new String("Hello World");
String s5 = new String("Hello Worlda");
String s6 = "d";
System.out.println(s1.length());//11
System.out.println(s1.charAt(8));//r
System.out.println(s1.isEmpty());//false
System.out.println(s1.toLowerCase());//hello world
System.out.println(s1.toUpperCase());//HELLO WORLD
System.out.println(s2.trim());//boom shit
System.out.println(s1.equals(s3));//true
System.out.println(s1.equals(s4));//true
System.out.println(s1.equalsIgnoreCase(s3.toUpperCase()));//true
System.out.println(s1.concat(s3));//Hello WorldHello World
System.out.println(s1.compareTo(s5));//-1
System.out.println(s1.substring(3));//lo World
System.out.println(s1.substring(3,7));//lo W
System.out.println(s1.endsWith(s6));//true
System.out.println(s1.endsWith(s3));//true
System.out.println(s1.startsWith(s3));//true
System.out.println(s1.startsWith("he",0));//false
String s7 = "hello world";
String s8 = new String("hello");
System.out.println(s7.contains(s8));//true
System.out.println(s7.indexOf("lo"));//3
System.out.println(s7.indexOf("l",3));//3
System.out.println(s7.indexOf("es"));//-1
String s9 = new String("abbccddccbba");
//索引從左邊開始計數,而不是按搜尋順序計數
System.out.println(s9.lastIndexOf("bb"));//9
System.out.println(s9.lastIndexOf("bb",6));//1
System.out.println(s9.lastIndexOf("ee"));//-1
String t1 = "Hello World";
String t2 = new String("boom shit");
String t4 = "ff";
String t3 = t1.replace("Hello", t2);
String t5 = t1.replace(t1, t4);
System.out.println(t3);//boom shit World
System.out.println(t5);//ff
String t6 = "大大得到的道德";
String t7 = t6.replace('大', '小');
String t8 = t6.replace("道德", "答覆");
System.out.println(t7);//小小得到的道德
System.out.println(t8);//大大得到的答覆
String str1 = "12hello23world13java2322mysql2323";
String str2 = str1.replaceAll("\\d+", ",");
System.out.println(str2);//,hello,world,java,mysql,
String str3 = str2.replaceAll("^,|,$", "");
System.out.println(str3);//hello,world,java,mysql\
String str5 = new String("12345");
boolean matches = str5.matches("\\d+");
System.out.println(matches);//true
}
}
String與基本資料型別、包裝類之間的轉換
-
String-->基本資料型別、包裝類:
-
呼叫包裝類的靜態方法:parseXxx(str)
-
基本資料型別、包裝類-->String:
- 呼叫String過載的valueOf(xxx)
@Test
public void test1(){
String str1 = "123";
// int num = (int)str1;//錯誤
int i = Integer.parseInt(str1);
System.out.println(i);
i++;
String str2 = String.valueOf(i);
String str3 = i +"";
System.out.println(str1==str3);//false
}
String與char[]之間的轉換
-
String-->char[]:
- 呼叫String的tocharArray();
-
char[] -->String :
- 呼叫String的構造器
@Test
public void test2(){
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (char i :charArray) {
System.out.println(i);
}
char[] arr =new char[]{'h', 'e', 'l', 'l', 'o'};
String str2 = new String(arr);
System.out.println(str2);//hello
}
String與byte[]之間的轉換
編碼:String-->byte[]:呼叫String的getBytes()
解碼:byte[]-->String:呼叫String的構造器
編碼:字串-->位元組
解碼:位元組-->字串
解碼時,要求解碼使用的字符集必須與編碼時使用的字符集一致,否則會出現亂碼。
@Test
public void test3() throws UnsupportedEncodingException {
String str1 = "abc123中國";
byte[] bytes = str1.getBytes();//使用預設的字符集,進行編碼
System.out.println(Arrays.toString(bytes));
byte[] gbks = str1.getBytes("gbk");//使用gbk字符集進行編碼
// for (byte i:gbks) {
// System.out.print(i+" ");
// }
System.out.println(Arrays.toString(gbks));
System.out.println();
String str2 = new String(bytes);//使用預設字符集進行解碼
System.out.println(str2);//abc123中國
String str3 = new String(gbks);
System.out.println(str3);//出現亂碼。原因;編碼集和解碼集不一致
String gbk = new String(gbks, "gbk");
System.out.println(gbk);//abc123中國
}
String、StringBuffer和StringBuilder三者的異同
String:不可變的字元序列:底層用final char[]儲存
StringBuffer:可變的字元序列,執行緒安全的,效率低,底層用char[]儲存
StringBuilder:可變的字元序列,執行緒不安全的,效率高,底層用char[]儲存
String、StringBuffer和StringBuilder三者相互轉換
呼叫轉換類的構造器就行
原始碼分析:
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(1,'k');
System.out.println(sb1);//akc
String str = new String();//final char[] value = new char[0];
String str1 = new String("abc");//final char[] value = new char[]{'a','b','c'};
StringBuffer sb2 = new StringBuffer();//char[] value = new char[16];底層建立了一個長度為16的陣列
System.out.println(sb2.length());//0
sb2.append('a');//value[0] = 'a';
sb2.append('b');//value[1] = 'b';
sb2.append('c');//value[2] = 'c';
System.out.println(sb2);//abc
System.out.println(sb2.length());//3
StringBuffer sb3 = new StringBuffer("abcd");//char[] value = new char["abc".length()+16];
/**
* 擴容問題:
* 預設情況下,擴容為原來容量的2倍+2,同時將原來陣列中的元素複製到新的陣列中去
* 指導意義:建議使用:StringBuffer(int capacity)或StringBuilder(int capacity)
*/
StringBuffer類常用方法
以上方法支援方法鏈原理,原理如下
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
遍歷需要for迴圈
for (int i = 0;i<stringbuffer.length();i++) {
System.out.println(stringbuffer.charAt(i));
}
@Test
public void test1(){
StringBuffer sb1 = new StringBuffer("abc");
char[] ch = {'a','c'};
sb1.append(1).append(ch);
System.out.println(sb1);//abc1ac
sb1.delete(1,4);
System.out.println(sb1);//aac
String str1 = new String("lll");
sb1.replace(1,2,str1);
System.out.println(sb1);//alllc
sb1.insert(0,123);
System.out.println(sb1);//123alllc
sb1.reverse();
System.out.println(sb1);//cllla321
sb1.setCharAt(3,'A');
System.out.println(sb1);//cllAa321
System.out.println(sb1.substring(1,3));//ll
}
JDK8之前的日期時間API
java.lang.System類
System類提供的public static long currentTimeMillis()用來返回當前時間與1970年1月1日之間以毫秒為單位的時間差。
@Test
public void test1(){
System.out.println(currentTimeMillis());
}
可用於訂單編號
java.util.Date類
Date類的兩個構造器的使用:
- Date():建立一個對應當前時間的Date物件
- Date(long)建立指定毫秒數的Date物件
java.util.Date類常用方法
@Test
public void test1(){
Date date1 = new Date();
System.out.println(date1.toString());//Sat Dec 05 00:43:41 CST 2020
System.out.println(date1.getTime());//1607100221127
Date date2 = new Date(1606997024829L);
System.out.println(date2.toString());//Thu Dec 03 20:03:44 CST 2020
}
建立java.sql.Date物件
java.sql.Date date3 = new java.sql.Date(1607100221127L);
System.out.println(date3);//2020-12-05
如何將java.util.Date物件轉換為java.sql.Date物件
//方法一:
Date date4 = new java.sql.Date(1607100422833L);
java.sql.Date date5 = (java.sql.Date) date4;
System.out.println(date5);//2020-12-05
//方法二:
Date date6 = new Date();
java.sql.Date date7 = new java.sql.Date(date6.getTime());
System.out.println(date7);//2020-12-05
SimpleDateFormat類
該類是一個不與語言環境有關的方式來格式化和解析日期的具體類
它允許進行格式化:日期-->文字
解析:文字-->日期
@Test
public void test1() throws ParseException {
//例項化SimpleDateFormat:使用預設的構造器
SimpleDateFormat sdf = new SimpleDateFormat();
Date date = new Date();
System.out.println(date);//Sat Dec 05 01:52:35 CST 2020
//格式化:日期-->字串
String format = sdf.format(date);
System.out.println(format);//20-12-5 上午1:52
//解析:字串-->日期
String str = "20-12-34 下午3:32";
Date date1 = sdf.parse(str);
System.out.println(date1);//Sun Jan 03 15:32:00 CST 2021
//呼叫有參構造器
// SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyy.MMMMM.dd GGG hh:mm aaa");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");//按照指定方式解析
//格式化
String format1 = sdf2.format(date);
System.out.println(format1);//2020-12-05 02:06:37
//解析 要求解析的字串必須符合SimpleDateFormat格式(通過SimpleDateFormat構造器有參引數體現)
Date date2 = sdf2.parse("2020-12-05 02:06:37");
System.out.println(date2);//Sat Dec 05 02:06:37 CST 2020
}
練習一:字串"2020-09-08"轉換為java.sql.Date
@Test
public void test1() throws ParseException {
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = sdf1.parse("2020-09-08");
System.out.println(date1);
java.sql.Date date2 = new java.sql.Date(date1.getTime());
System.out.println(date2);
}
練習二:從1990-01-01開始“三天打漁兩天晒網“,2020-09-08是打漁還是晒網?
@Test
public void test2() throws ParseException {
//1990-01-01 2020-09-08
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = simpleDateFormat.parse("1990-01-01");
long time1 = date1.getTime();
SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
Date date2 = simpleDateFormat1.parse("2020-09-08");
long time2 = date2.getTime();
long timeSub = time2 - time1;
long i = 86_400_000L;//一天的毫秒數
long day = timeSub / i ;
int j = (int)day%5;
switch (j){
case 0:
System.out.println("晒網");
break;
case 1:
System.out.println("打漁");
break;
case 2:
System.out.println("打漁");
break;
case 3:
System.out.println("打漁");
break;
case 4:
System.out.println("晒網");
break;
}
}
Calendar類(抽象類)
例項化方法:
- 建立其子類GregorianCalendar的物件
- 呼叫其靜態方法getInstance()
@Test
public void test1(){
Calendar calendar = Calendar.getInstance();
//get()
int days = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(days);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//set()
calendar.set(Calendar.DAY_OF_YEAR,13);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//add()
calendar.add(Calendar.DAY_OF_YEAR,33);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
//getTime() 日曆類-->Date
Date date = calendar.getTime();
System.out.println(date);
//setTime() Date-->日曆類
Date date1 = new Date();
calendar.setTime(date1);
System.out.println(calendar.get(Calendar.DAY_OF_YEAR));
}
Calendar的常用方法:
LocalDate、LocalTime、LocalDateTime
常用方法:
@Test
public void test(){
//例項化方式:now(),of()
//now()
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
/*
2020-12-05
14:53:33.926
2020-12-05T14:53:33.926
*/
System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);
//of() 設定指定的年,月,日,時,分,秒,沒有偏移量
LocalDateTime localDateTime1 = LocalDateTime.of(2020, 12, 22, 15, 22,33);
System.out.println(localDateTime1);//2020-12-22T15:22:33
System.out.println("==================================");
//getXxx()
System.out.println(localDateTime1.getDayOfMonth());//22
System.out.println(localDateTime1.getDayOfYear());//357
System.out.println(localDateTime1.getDayOfWeek());//TUESDAY
System.out.println(localDateTime1.getMonth());//DECEMBER
System.out.println(localDateTime1.getMonthValue());//12
System.out.println(localDateTime1.getMinute());//22
System.out.println(localDateTime1.getSecond());//33
//體現不可變性
//withXxx():設定相關屬性
LocalDateTime localDateTime2 = localDateTime1.withDayOfMonth(22);
System.out.println(localDateTime1);//2020-12-30T15:22:33
System.out.println(localDateTime2);//2020-12-22T15:22:33
LocalDateTime time3 = localDateTime1.plusDays(2);
System.out.println(time3);//2020-12-24T15:22:33
LocalDateTime time4 = localDateTime1.minusHours(3);
System.out.println(time4);//2020-12-22T12:22:33
}
Instant類
常用方法
@Test
public void test1(){
Instant now = Instant.now();
System.out.println(now);//返回的時間時本初子母線的時間
}
DateTimeFormatter類
格式化或解析日期、時間
@Test
public void test3(){
DateTimeFormatter time3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
//格式化
String s = time3.format(LocalDateTime.now());
System.out.println(s);//2020-12-05 03:36:08
//解析
TemporalAccessor accessor = time3.parse("2020-12-30 05:22:33");
System.out.println(accessor);//{NanoOfSecond=0, SecondOfMinute=33, MicroOfSecond=0, MilliOfSecond=0, MinuteOfHour=22, HourOfAmPm=5},ISO resolved to 2020-12-30
}
Java比較器
使用Comparable介面和Comparator,對物件進行排序.
Comparable介面的使用舉例:自然排序
- String、包裝類等實現了Comparable介面,重寫了compareTo(obj)方法,給出了比較兩個物件大小的方式。
- String、包裝類重寫compareTo()方法以後,進行了大小排列。
- 重寫compareTo(obj)的規則:
- 如果當前物件this大於形參物件obj,則返回正整數,
- 如果當前物件this小於形參物件obj,則返回負整數,
- 如果當前物件this等於於形參物件obj,則返回0。
- 對於自定義類來說,如果需要排序,我們可以讓自定義類來實現Comparable介面,重寫compareTo(obj)方法.
package compareTest;
public class Goods implements Comparable{
private String name;
private double price;
public Goods() {
}
public Goods(String name, double price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//指明排序方式
@Override
public int compareTo(Object o) {
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;
}
throw new RuntimeException("資料有問題");
}
}
package compareTest;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
public class CompareTest {
@Test
public void test(){
Goods[] arr = new Goods[4];
arr[0] = new Goods("lenovn",5);
arr[1] = new Goods("dell",6);
arr[2] = new Goods("xiaomi",3);
arr[3] = new Goods("huawei",9);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[Goods{name='xiaomi', price=3.0}, Goods{name='lenovn', price=5.0}, Goods{name='dell', price=6.0}, Goods{name='huawei', price=9.0}]
}
}
Comparator介面的使用:定製排序
-
背景:
- 當元素的型別沒有實現Comparable介面而又不方便修改程式碼,或者實現了Comparable介面但排序規則不適合當前的操作。
-
重寫comparator(object o1,object o2)方法,比較o1和o2的大小:
返回正整數,o1>o2
返回負整數,o1<o2
返回0,o1=o2
@Test
public void test1(){
String[] arr = new String[]{"AA","CC","FF","EE","DD","GG","HH"};
Arrays.sort(arr,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof String && o2 instanceof String){
String s1 = (String) o1;
String s2 = (String) o2;
return s1.compareTo(s2);
}
throw new RuntimeException("輸入的資料型別不一致");
}
});
System.out.println(Arrays.toString(arr));
}
二者對比
- Comparable介面的方式一旦一定,保證Comparable介面實現類的物件在任何位置都可以比較大小。
- Comparator介面屬於臨時性的比較。