Java基礎篇(02):特殊的String類,和相關擴展API

来源:https://www.cnblogs.com/cicada-smile/archive/2020/03/08/12445768.html
-Advertisement-
Play Games

本文源碼: "GitHub·點這裡" || "GitEE·點這裡" 一、String類簡介 1、基礎簡介 字元串是一個特殊的數據類型,屬於引用類型。String類在Java中使用關鍵字final修飾,所以這個類是不可以繼承擴展和修改它的方法。String類用處極廣泛,在對String對象進行初始化時 ...


本文源碼:GitHub·點這裡 || GitEE·點這裡

一、String類簡介

1、基礎簡介

字元串是一個特殊的數據類型,屬於引用類型。String類在Java中使用關鍵字final修飾,所以這個類是不可以繼承擴展和修改它的方法。String類用處極廣泛,在對String對象進行初始化時,和基本類型的包裝器類型一樣,可以不使用new關鍵字構造對象。(是真的妖嬈...)

2、類構造和方法

  • String類結構

特點:final關鍵字修飾,實現Serializable序列化介面,Comparable比較介面,和CharSequence字元序列介面。

final class String
    implements java.io.Serializable,
    Comparable<String>, CharSequence
  • 聲明方式

兩種方式,常量和創建對象。

String var1 = "cicada" ;           
String var2 = new String("smile") ;

var1:聲明的是一個常量,顯然是放在常量池中。

var2:創建字元串對象,對象存放在堆記憶體中。

二、常見應用

1、比較判斷

常量池用來存放常量;堆記憶體用來存放new出來的引用對象。

public class String02 {
    public static void main(String[] args) {
        String var1 = "cicada" ;
        String var2 = "cicada" ;
        // true;true
        System.out.println((var1==var2)+";"+var1.equals(var2));
        String var3 = new String("cicada");
        String var4 = new String("cicada");
        // false;true
        System.out.println((var3==var4)+";"+var3.equals(var4));
        // false;true
        System.out.println((var1==var4)+";"+var2.equals(var4));
        String var5 = "ci"+"cada";
        // true;true
        System.out.println((var1==var5)+";"+var5.equals(var4));
        String var6 = new String02().getVar6 () ;
        // true;true
        System.out.println((var1==var6)+";"+var6.equals(var4));
    }
    public String getVar6 (){
        return "cicada" ;
    }
}

==:對於基本類型,比較的是值,對於引用類型,比較的是地址的值;

equals:該方法源自Object中一個最基礎的通用方法,在Object的方法中使用==判斷地址的值,只是到了String類中進行了重寫,用於字元內容的比較,該方法在繼承關係中的變化,追蹤JDK源碼,變化非常清楚。

2、編碼解析

字元串在String內部是通過一個char[]數組表示,Unicode統一的編碼表示的字元,char類型的字元編碼由此來。

  • 構造源碼

這裡看下構造方法就會明白上面的概念邏輯。

private final char value[];
public String() {this.value = "".value;}
public String(String original) {
    this.value = original.value;
    this.hash = original.hash;
}
  • 編碼轉換

不同的國家和地區,使用的編碼可能是不一樣的,互聯網中有UTF8編碼又是最常用,一次在程式開發中,經常需要編碼之間轉換。

public class String03 {
    public static void main(String[] args) throws Exception {
        String value = "Hello,知了";
        // UTF-8
        byte[] defaultCharset = value.getBytes(Charset.defaultCharset());
        System.out.println(Arrays.toString(defaultCharset));
        System.out.println(new String(defaultCharset,"UTF-8"));
        // GBK
        byte[] gbkCharset = value.getBytes("GBK");
        System.out.println(Arrays.toString(gbkCharset));
        System.out.println(new String(gbkCharset,"GBK"));
        // ISO-8859-1:表示的字元範圍很窄,無法表示中文字元,轉換之後無法解碼
        byte[] isoCharset = value.getBytes("ISO8859-1");
        System.out.println(Arrays.toString(isoCharset));
        System.out.println(new String(isoCharset,"ISO8859-1"));
        // UTF-16
        byte[] utf16Charset = value.getBytes("UTF-16");
        System.out.println(Arrays.toString(utf16Charset));
        System.out.println(new String(utf16Charset,"UTF-16"));
    }
}

兩個基礎概念:

編碼Encode:信息按照規則從一種形轉換為另一種形式的過程,簡稱編碼;

解碼Decode:解碼就是編碼的逆向過程。

3、格式化操作

在日常開發中,字元串的格式不會都滿足業務要求,通常就需要進行指定格式化操作。

public class String04 {
    public static void main(String[] args) {
        // 指定位置拼接字元串
        String var1 = formatStr("cicada","smile");
        System.out.println("var1="+var1);
        // 格式化日期:2020-03-07
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date() ;
        System.out.println(format.format(date));
        // 浮點數:此處會四捨五入
        double num = 3.14159;
        System.out.print(String.format("浮點類型:%.3f %n", num));
    }
    public static String formatStr (String ...var){
        return String.format("key:%s:route:%s",var);
    }
}

上面案例演示應用場景:Redis緩存Key生成,日期類型轉換,超長浮點數的截取。

4、形參傳遞問題

String對象形參傳遞到方法里的時候,實際上傳遞的是引用的拷貝。

public class String05 {
    String var1 = "hello" ;
    int[] intArr = {1,2,3};
    public static void main(String[] args) {
        String05 objStr = new String05() ;
        objStr.change(objStr.var1,objStr.intArr);
        // hello  4
        System.out.println(objStr.var1);
        System.out.println(objStr.intArr[2]);
    }
    public void change (String var1,int[] intArr){
        var1 = "world" ;
        intArr[2] = 4 ;
    }
}

案例中改變的是var1引用的拷貝,方法結束執行結束,形參var1被銷毀, 原對象的引用保持不變。數組作為參數傳遞時傳遞是數組在記憶體中的地址值,這樣直接找到數組在記憶體中的位置。

5、String工具類

字元串的處理在系統開發中十分的常見,通常會提供一個工具類統一處理,可以基於一個框架中的工具類二次封裝,也可以全部自行封裝。

class StringUtil {
    private StringUtil(){}
    public static String getUUid (){
        return UUID.randomUUID().toString().replace("-","");
    }
}

上面是字元串工具類最基礎的一個。不同框架中自帶的工具類也不錯。

org.apache.commons.lang3.StringUtils
org.springframework.util.StringUtils
com.alibaba.druid.util.StringUtils

這裡推薦第一個,也可以把自定義的工具類繼承該工具類,提供更豐富的公共方法。

絮叨一句:代碼整潔之道的基礎,就是有一顆《偷懶》的心,花點心思該封裝的封裝,該刪除的刪除。

三、擴展API

1、StringBuffer類

字元串修改拼接常用的API,內部的實現過程和String類似。

public class String07 {
    public static void main(String[] args) {
        StringBuffer var = new StringBuffer(2) ;
        var.append("what");
        var.append("when");
        System.out.println(var);
    }
}

看到上面幾行代碼的反應,基本能反應編程的年齡:

一年:API是這樣用的,沒毛病;

三年:StringBuffer是線程安全的,效率相對偏低;

五年:預設字元數組大小是16,這裡自定義字元數組的大小,如果長度不夠需要擴容,所以要預估一下字元串的可能大小,減小消耗;

絮叨一句:Java中許多容器對象的大小預設是16,且具備動態擴容機制,這就是傳說中的編程思想,在開發中照葫蘆畫瓢的寫兩段,這就是格調。

2、StringBuilder類

這個類出現比StringBuffer要晚很多,從JDK1.5才開始出現。

public class String08 {
    public static void main(String[] args) {
        StringBuilder var = new StringBuilder() ;
        var.append("how").append("what") ;
        System.out.println(var);
    }
}

用法和StringBuffer差不多,不過是非線程安全操作,效率自然要高。

補刀一句:對於線程安全和操作和非安全操作,還有初始容量和擴容這種邏輯,都可以在源碼中查看,這是進階程式員的必備意識。

3、再看傳參問題

這裡原理解釋同上,根本邏輯是一致的。

public class String09 {
    public static void main(String[] args) {
        String var1 = new String("A");
        String var2 = new String("B");
        StringBuffer var3 = new StringBuffer("C");
        StringBuffer var4 = new StringBuffer("D");
        join(var1,var2);
        join(var3,var4);
        //A<>B
        System.out.println(var1+"<>"+var2);
        //C<>DD
        System.out.println(var3+"<>"+var4);
    }
    public static void join (String s1,String s2){
        s1 = s2 ;
        s2 = s1+s2 ;
    }
    public static void join (StringBuffer s1,StringBuffer s2){
        s1 = s2 ;
        s2 = s2.append(s1) ;
    }
}

絮叨一句:String相關API傳參問題,工作前三年跳槽基本都會被問到,如果不瞭解基本原理,心情再有點小慌,還基本會答錯。

四、源代碼地址

GitHub·地址
https://github.com/cicadasmile/java-base-parent
GitEE·地址
https://gitee.com/cicadasmile/java-base-parent


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [TOC] 前言 工廠模式,顧名思義就是我們可以通過一個指定的“工廠”獲得需要的“產品”. 在 設計模式 中主要用於抽象 ,讓用戶可以指定自己想要的對象而不必關心對象的實例化過程。 這樣做的好處是用戶只需通過固定的介面而不是直接去調用類的實例化方法來獲得一個對象的實例,隱藏了實例創建過程的複雜度,解 ...
  • 記錄大話設計模式學習,大話設計模式pdf分享:鏈接:https://pan.baidu.com/s/11h9x-4RffXydf3GFH5_y7g 提取碼:x5c3 實現簡單計算器的加減乘除運算,做到可維護、可擴展、可復用、且靈活。 可維護舉例:業務人員要求加法功能只允許絕對值相加,這時修改代碼的區 ...
  • Description Service Mesh 架構下,服務間調用會通過服務名(Service Name)互相調用,比如在 Kubernetes 、Docker Swarm 集群中,服務 IP 均由集群動態分配,外部網路無法直接訪問到集群內部的服務。對於大型系統,微服務的數量較多,服務間的調用關係 ...
  • 一、軟體開發設計原則:(七大原則) 開閉原則:軟體實體對擴展開放、對修改關閉(用抽象構建架構,用實現擴展細節) 單一職責原則:類或介面的職責要單一、只做一件事,保證功能的單一性、純潔性 依賴倒置原則:要針對抽象層編程,而不要針對具體實現類編程 介面隔離原則:一個介面不要包含過多的職責,應合理劃分,跟 ...
  • 一、JDK5.0新特性 1.增強for迴圈 2.語法 for(類型 變數:數組名/集合名){} 集合想要使用增強for迴圈這種語法,集合需要使用泛型。 如果不使用泛型,那麼需要哦使用Object類型來定義集合中的元素 package com.bjpowernode.java_learning; im ...
  • 折半查找的應用 public static void main(String[] args) { int[] arr = {4,6,6,7,8,9,10}; System.out.println(getIndexOf(arr,5)); } public static int getIndexOf(i ...
  • public static void main(String[] args) { int[] arr = {0,1,2,3,4,5,6,7,8,9,10}; System.out.println(halfSearch_2(arr,5)); } public static int halfSearch ...
  • Python 第三方庫國內鏡像下載地址 由於 Python 伺服器在國外,因此使用 pip 安裝第三方模塊或者庫的時候,下載速度特別慢,經常出現如下報錯: $ socket.timeout: The read operation timed out 為提升下載速度,可以使用國內鏡像下載,常用的國內鏡 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...