淺談API的學習方法
在後續的學習過程中,還會大量使用JDK或者第三方元件、框架提供的API,而在學習這些API時可以利用面向物件的思想去使用它們。
瞭解它的體系結構,即它繼承了哪個父類,在Java領域預設都是直接間接繼承java.lang.Object,如果父類是一個抽象類,需要抽象類的方法,還有就是實現了哪個介面,介面中的方法都應該被實現類實現。瞭解它的成員變數,瞭解底層實現。瞭解它的構造方法,構造方法用於建立該類的物件,如果它的構造器是私有的,那麼它通常是一個工具類,提供的方法都是靜態方法,直接透過類名.方法名呼叫即可。瞭解它的普通方法,主要是關注方法如何呼叫,關於方法主要是方法的過載、重寫、引數和返回值,宣告的異常。多看原始碼,主要是方法的實現,多除錯流程,多仿寫,多改寫String類String類概述java.lang.String類表示字串,字串是日常開發中最常用的資料型別。
因為Java主要是做服務端,也就是後端。當前端發起HTTP請求傳給後端的資料格式是字串,也就是String類。在Java程式中所有使用一對雙引號("")包含的內容(例如“helloworld”)都是String物件的例項。
String類特性String類是基於位元組陣列實現的,當操作字串時底層是一個位元組陣列,而且該陣列是final,也就是必須只能賦一次值,因此說String類是不可變的,每操作一次都會產生一個新的位元組陣列
/** * String的特點:不可變 */ @Test public void testStringFeatureImmutable(){ String str1="abc"; str1+="d"; //此時記憶體中有三個字串物件,分別是abc,d,abcd,字串的任何操作都會產生一個新的String物件 }
而同一個字串常量是可以被共享的,即同一個字串在JVM中只會有一個字串物件。
/** * 兩個相同的字串在JVM中只會儲存一個字串物件 */ @Test public void testStringFeatureShare(){ String str1="abc"; String str2="abc"; }
建立 String物件的幾種方式在使用String之前,需要藉助String類的構造器建立該類的物件。日常開發中可以透過字串常量,位元組陣列和字元陣列三種方式來建立String類的物件,也可以直接使用字串常量賦值給String型別的變數建立一個String型別的物件。
/** * String物件的幾種建立方式 */ @Test public void testStringConstruct(){ // 方式1 //直接將字面量的值賦值也是字串物件 String str="hello"; System.out.println("str = "+str); /*3種構造方式*/ //方式2 //空字串 String emptyString=new String(""); System.out.println("emptyString = "+emptyString); //方式3 //將位元組陣列轉換為字串 //列印的是ABCDEF byte[] bytes=new byte[]{65,66,67,68,69,70}; String byteArray=new String(bytes); System.out.println("byteArray = "+byteArray); //列印結果是cde String byteArrayBetweenAnd=new String(bytes,2,3); System.out.println("byteArrayBetweenAnd = "+byteArrayBetweenAnd); //方式4 //將字元陣列轉換為字串 char[]chars=new char[]{'a','b','c'}; String charArray=new String(chars); System.out.println("charArray = "+charArray); }
程式執行結果
使用new關鍵字建立的字串物件,每次都會在堆記憶體中開闢記憶體空間,雖然字串內容相同,但是地址值不同。但是當將一個字串常量賦值給一個字串變數時,此時的字串常量儲存在常量池當中,相同的字串常量JVM只會儲存一份,也就是同一個String物件。
/** 字串物件儲存的差異 */ @Test public void testStringInstanceDiff() { char[] chars = {'a', 'b', 'c'}; String str1 = new String(chars); String str2 = new String(chars); // ==比較的是記憶體地址,因為每次new都會在堆記憶體申請新的空間 因此地址值是不相等 System.out.println("str1 == str2 " + (str1 == str2)); // 此時abc位於常量池中,相同的常量值JVM只會儲存一份 String str3="abc"; String str4="abc"; //此時兩個引用變數是相等的,因為str3和str4的變數值都位於常量區,它倆都指向同一個常量區地址 System.out.println("str3 == str4 " + (str3 == str4)); }
字串儲存記憶體結構
程式執行結果
String物件常用方法的使用字串比較的方法字串比較是日常開發中常用的方法,String物件提供了兩個方法用於字串物件的比較:equal()方法和equalsIgnoreCase()方法equals()方法用於比較兩個字串物件是否相等,不忽略大小寫。equalsIgnoreCase()方法用於比較兩個字串物件是否相等,忽略大小寫。在開發中不要使用==判斷引用資料型別是否相等,因為預設比較的是引用變數的地址值。 /** * 字串相等性比較 * == 操作基本資料型別比較的是變數值是否相同 * == 操作引用資料型別比較的是地址值是否相等 * equals()方法用於比較兩個字串相等,不忽略大小寫 * equalsIgnoreCase()方法用於比較兩個字串是否相等,忽略大小寫 * */ @Test public void testStringEquals(){ int source=10; int target=10; System.out.println("source == target ="+(source==target)); String str1="abc"; char[] chars={'a','b','c'}; String str2=new String(chars); // 因此不能使用==判斷兩個字串物件的內容是否相等 System.out.println("str1 == str2 ="+(str1 == str2)); // 比較兩個字串物件的內容相同使用equals()方法,返回一個布林值,區分大小寫 System.out.println("str1.equals(str2) = "+str1.equals(str2)); //例如abc和ABC會返回false String str3="ABC"; System.out.println("str1.equals(str3) = "+(str1.equals(str3))); //某些應用場景會忽略大小寫,例如驗證碼,此時可以使用equalsIgnoreCase()方法 System.out.println("str1.equalsIgnoreCase(str3) = "+(str1.equalsIgnoreCase(str3))); }
程式執行結果
獲取字串length()方法用於獲取字串的長度,其本質就是除了\0以外的字元個數concat()方法用於字串的拼接,等價於+charAt(int index) 方法用於查詢指定索引的字元,結合for迴圈可以實現字串的遍歷indexOf(String str)查詢指定字串第一次出現的索引位置,還有個過載的方法indexOf(String str,int index),可以實現獲取指定第n個次出現的字串lastIndexOf(String str) 反向查詢指定的字串出現的索引位置subString(int beginIndex) 按照指定的開始索引擷取字串subString(int beginIndex,int endIndex) 按照指定的開始索引和結束索引擷取字串,擷取的字串不包含結束索引的字串 /** * 獲取字字串 */ @Test public void testStringGet(){ String str="HelloWorld"; //獲取字串的長度 int length =str.length(); System.out.println("HelloWorld字串的長度是 "+length); //等價於 HelloWorld+你好,世界 String concatStr = str.concat("你好,世界"); System.out.println("拼接後字串內容是"+concatStr); System.out.println("拼接之前的字串內容是"+str); //獲取2索引位置的元素 char charValue=str.charAt(2); System.out.println("HelloWorld字串第二個索引的元素是"+charValue); //結合for迴圈,length()方法和charAt()方法實現字串的遍歷 for (int i = 0; i < str.length(); i++) { System.out.print(str.charAt(i)+","); } System.out.println(); int firstLIndex=str.indexOf("l"); System.out.println("HelloWorld字串的第一個l字元的索引是"+firstLIndex); //獲取HelloWorld字串的第二個字串 int secondLIndex=str.indexOf("l",firstLIndex+1); System.out.println("HelloWorld字串的第二個l字元的索引是"+secondLIndex); //獲取HelloWorld字串倒數第一個字串l int lastFirstLIndex=str.lastIndexOf("l"); System.out.println("HelloWorld字串的倒數第一個l字元的索引是"+lastFirstLIndex); //擷取HelloWorld的World String hello=str.substring(5); System.out.println("HelloWorld擷取Hello的結果是"+hello); //擷取HelloWorld的Hello String subString=str.substring(0,5); System.out.println("HelloWorld擷取Hello的結果是"+subString); }
程式執行結果
字串的非空判斷字串非空判斷是經常使用到的,在判斷之前需要先判斷物件是不是null,然後再使用isEmpty()方法判斷物件的內容是不是空
/** * 字串的非空判斷 */ @Test public void testStringEmpty(){ //空,沒有在堆記憶體分配記憶體空間,str1不能使用,如果使用會引發空指標 String str1=null; // 此處會拋空指標 // boolean str1IsEmpty=str1.isEmpty(); //空字串物件,已經在堆記憶體分配記憶體空間,只是空間沒有內容,沒有內容,即byte[]沒有元素 String str2=""; boolean str2IsEmpty=str2.isEmpty(); System.out.println("str2IsEmpty = " +str2IsEmpty); //包含一個空格的字串 String str3=" "; boolean str3IsEmpty=str3.isEmpty(); System.out.println("str3IsEmpty = " +str3IsEmpty); }
程式執行結果
判斷字串是否包含指定的字串和字串的替換 /** * contains() 字串是否包含字串 * replace()字串替換 */ @Test public void testStringContainsReplace(){ String parent="跟光磊學Java"; boolean isContains=parent.contains("Java"); System.out.println("字串跟光磊學Java是否包含Java?"+isContains); if(isContains){ //將Java替換成前端 parent=parent.replace("Java","前端"); } System.out.println("將Java替換成前端後 parent = "+parent); }
程式執行結果
5. 字串大小寫轉換
/** * 字串大小寫轉換 * toLowerCase() 字串轉換為小寫 * toLowerCase() 字串轉換為大寫 */ @Test public void testStringUpperLower(){ String upper="ABC"; System.out.println("ABC轉換為小寫的結果是"+upper.toLowerCase()); String lower="abc"; System.out.println("abc轉換為大寫的結果是"+lower.toUpperCase()); }
程式執行結果
字串和字元陣列、位元組陣列的轉換字串轉換為位元組陣列時會將字元替換成對應的ASCII值/** * toCharyArray()字串轉換為字元陣列 * 字串轉換為位元組陣列 */ @Test public void testStringToCharArrayByteArray(){ String str="HelloWorld"; char[] chars = str.toCharArray(); System.out.println("HelloWorld轉換為字元陣列的結果是" + Arrays.toString(chars)); byte[] bytes = str.getBytes(); System.out.println("HelloWorld轉換為位元組陣列的結果是" + Arrays.toString(bytes)); }
程式執行結果
字串刪除首尾空格 /** * trim()字串去掉首位空格 * */ @Test public void testStringTrim() { String str=" Hello World "; System.out.println("去掉空格前是"+str); System.out.println("掉空格後的結果是"+str.trim()); }
程式執行結果
字串按照指定的規則拆分 /** * split(String regex)按照指定的規則拆分字串 */ @Test public void testStringSplit(){ String language="C,Java,JavaScript,Go,Python,C++"; //按照逗號拆分字串 String[]languages=language.split(","); System.out.println("必須掌握的程式語言:"+Arrays.toString(languages)); }
程式執行結果
實現Arrays.toString()方法/** 實現Arrays.toString(int[]a)方法 */ @Test public void testStringConcat() { int[] numbers = {1, 2, 4, 5, 7, 8, 9, 6, 3}; //初始化拼接字串 String str = new String("["); //遍歷數字 for (int i = 0; i < numbers.length; i++) { if (i < numbers.length - 1) { //不是最後數字就拼接數字和逗號 str = str.concat(numbers[i] + ","); } else if (i < numbers.length) { //是最後數字就拼接數字和] str = str.concat(numbers[i] + "]"); } } System.out.println(str); }
程式執行結果
字串反轉 /** 字串反轉 */ @Test public void testStringInversion() { String str = "跟光磊學Java開發"; System.out.println("跟光磊學Java開發反轉之前 str = " + str); String result = new String(); for (int i = str.length()-1; i >= 0; i--) { result+=str.charAt(i); // } System.out.println("跟光磊學Java開發反轉之後 result = " + result); }
字串反轉
StringBuilder類StringBuilder類概述由於String的不可變特性,每次操作都會產生一個新的String物件,這樣耗時號記憶體。因此SUN公司又設計了StringBuilder類
java.lang.StringBuilder表示 一個可變的字串類,這裡的可變表示StringBuilder物件中的內容是可變的。透過其父類java.lang.AbstractStringBuilder的原始碼可以看出它的底層實現採用一個不是final修飾的位元組陣列。
StringBuilder類的構造方法在使用StringBuilder物件提供的方法之前,同樣需要建立StringBuilder的物件。我們可以使用兩種方法來建立StringBuilder物件:空字串建立StringBuilder物件和非空字串建立StringBuilder()物件
/** StringBuilder常用構造器 */ @Test public void testStringBuilderConstruct() { // 使用空字串建立一個StringBuilder物件 StringBuilder emptyString = new StringBuilder(); System.out.println("emptyString.length() = " + emptyString.length()); // 使用字串建立一個StringBuilder物件 String str = "跟光磊學Java程式設計"; StringBuilder content = new StringBuilder(str); System.out.println("content.length() = " + content.length()); }
程式執行結果
如果使用空字串建立StringBuilder物件,透過原始碼得知,預設會開闢長度為16個位元組的長度
/** * Constructs a string builder with no characters in it and an * initial capacity of 16 characters. */ @HotSpotIntrinsicCandidate public StringBuilder() { super(16); } /** * Creates an AbstractStringBuilder of the specified capacity. */ AbstractStringBuilder(int capacity) { if (COMPACT_STRINGS) { value = new byte[capacity]; coder = LATIN1; } else { value = StringUTF16.newBytesFor(capacity); coder = UTF16; } }
StringBuilder常用方法在建立StringBuilder物件後就可以呼叫StringBuilder物件的方法。
使用StringBuilder實現字串拼接 /** * append():拼接任意型別的資料返回本身 */ @Test public void testStringBuilderAppend(){ StringBuilder emptyString=new StringBuilder(); emptyString.append(2020); emptyString.append("年"); StringBuilder result=emptyString.append("跟光磊學Java開發"); System.out.println(result); System.out.println("result==emptyString = "+(result==emptyString)); }
程式執行結果無論拼接多少次返回的都是同一個StringBuilder物件
在指定的位置插入字串 /** * insert():在指定的位置插入資料並返回本身 */ @Test public void testStringBuilderInsert(){ StringBuilder emptyString=new StringBuilder(); emptyString.append("跟光磊學Java開發,"); emptyString.append("跟光磊學Linux運維"); emptyString.insert(11,"跟光磊學前端開發,"); System.out.println(emptyString); }
程式執行結果
字串反轉 /** * reverse():反轉字串並返回 */ @Test public void testStringBuilderReverse(){ StringBuilder helloWorld=new StringBuilder("界世好你"); StringBuilder reverseResult = helloWorld.reverse(); System.out.println("reverseResult==helloWorld = "+(reverseResult==helloWorld)); System.out.println(helloWorld); }
程式執行結果
StringBuilder和String物件的相互轉換 /** * StringBuilder和String的相互轉換 */ @Test public void testStringBuilderToString(){ String str="HelloWorld"; //String轉StringBuilder StringBuilder content=new StringBuilder(str); //StringBuilder轉String str=content.toString(); }
使用StringBuilder實現Arrays.toString()方法 /** * 使用StringBuilder實現Arrays.toString()方法 */ @Test public void testStringBuilderAppendArray(){ int[] numbers=new int[]{1,2,4,5,7,8,9,6,3}; StringBuilder content = new StringBuilder("["); for (int i = 0; i < numbers.length ; i++) { if(i<numbers.length-1){ content.append(numbers[i]+","); }else if(i<numbers.length){ content.append(numbers[i]+"]"); } } System.out.println(content); }
程式執行結果
使用鏈式程式設計實現字串反轉/** * 使用StringBuilder實現字串反轉 */ @Test public void testStringBuilderReverseString(){ String str="發開avaJ學磊光跟"; String reverseStr=reverse(str); System.out.println(reverseStr); } /** * 定義一個字串反轉的方法返回元字串 * @param str * @return */ public String reverse(String str){ // 鏈式程式設計 return new StringBuilder(str).reverse().toString(); }
程式執行結果