1. 程式人生 > 實用技巧 >框架 Spring Boot 技術入門到整合 6-3 thymeleaf 常用標籤的使用方法

框架 Spring Boot 技術入門到整合 6-3 thymeleaf 常用標籤的使用方法

常用類

  1. 字串相關的類
    • String類及常用方法
    • StringBuffer
    • StringBuilder
  2. JDK8之前的日期時間API
    • System靜態方法---------->currentTimeMillis()
    • Date類
    • Calendar類
    • SimpleDateFormat類
  3. JDK8中新日期時間API
    • LocalDate
    • LocalTime
    • LocalDateTime
    • Instant
    • DateTimeFormatter
  4. Java比較器
    • Compara介面
    • Comparator介面
  5. System類
  6. Math類
  7. BigInteger與BigDecimal

String

  • String類:代表字串

  • String實現了Serializable介面:表示字串是支援序列化的。
    實現了Comparable介面:表示String可以比較大小

  • String內部定義了final char[] value用於儲存字串資料。

  • String:代表不可變的字元序列。簡稱:不可變性。

    • 體現:

      1. 當對字串重新賦值時,需要重寫指定記憶體區域賦值,不能使用原有的value進行賦值。
      2. 當對現有的字串進行連線操作時,也需要重新指定記憶體區域賦值,不能使用原有的value賦值。
      3. 當呼叫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介面的使用舉例:自然排序

  1. String、包裝類等實現了Comparable介面,重寫了compareTo(obj)方法,給出了比較兩個物件大小的方式。
  2. String、包裝類重寫compareTo()方法以後,進行了大小排列。
  3. 重寫compareTo(obj)的規則:
    • 如果當前物件this大於形參物件obj,則返回正整數,
    • 如果當前物件this小於形參物件obj,則返回負整數,
    • 如果當前物件this等於於形參物件obj,則返回0。
  4. 對於自定義類來說,如果需要排序,我們可以讓自定義類來實現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介面的使用:定製排序

  1. 背景:

    • 當元素的型別沒有實現Comparable介面而又不方便修改程式碼,或者實現了Comparable介面但排序規則不適合當前的操作。
  2. 重寫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介面屬於臨時性的比較。

System類

Math類

BigInteger

BigDecimal