JavaSE基础——常用类1
JavaSE基礎——常用類1
一、Object類
java.lang.Object類是Java語言中的根類,即所有類的父類。它當中描述的所有方法子類都可以使用。
如果在類的聲明中沒有顯式地使用extends來指明父類,則該類默認的父類就是java.lang.Object。
根據API文檔,Object類中包含的方法有11個:
-
toString()方法、equals()方法:詳細說明
-
hashCode()方法:返回對象的哈希碼值。(集合)
-
clone()方法:創建并返回對象的副本。
- getclass()方法
:返回對象所在的類。
- ``getclass().getSuperclass()方法`:返回對象所在的父類
-
finalize()方法:當垃圾收集確定不再有對該對象的引用時,垃圾收集器在對象上調用該方法。
- 垃圾回收機制只回收JVM堆內存里的對象空間。對其他類如數據庫連接、輸入輸出流、Socket連接等無能為力。
- 垃圾回收具有不可預知性,程序無法精準控制垃圾回收機制的執行。程序員可以通過System.gc()或者Runtime.getRuntime.gc()來通知系統進行垃圾回收,但系統什么時候進行不得而知
- 垃圾回收機制回收任何對象前,總會讓對象調用自身的finalize()方法。
- 可以將對象的引用變量設為null,來表明需要垃圾回收機制回收該對象。
-
notify()方法、 notifyAll()方法、 wait()方法(3個):(線程)
下面學習幾個主要的方法:
1. equals方法
1.1 ==運算符回顧
- ==是運算符,可以使用在基本數據類型和引用類型的比較
- 如果比較的是基本數據類型,則比較這兩個變量保存的值是否相等,此時與數據類型無關。比如:char類型的10和int類型的10是相等的,因為他們的值相等。
- 如果比較的是引用類型,則比較的是引用的地址值是否相等。即比較兩個引用是否指向同一個對象
1.2 equals方法
- equals()是一個方法,只能被對象調用,因此只能用于引用類型的比較
- Object類中的equals()方法和==運算符的作用是相同的,即都是比較引用的地址值是否相同,判斷是否指向同一個對象
- String類、包裝類、Data類、IO流等都重寫了Object類中的equals方法,重寫后都是比較兩個對象的內容是否相同。
1.3 equals方法的重寫
一般對于自定義的類,也想用equals方法比較兩個對象的內容是否一致,這時就需要重寫equals方法。
快捷鍵:Alt + insert 生成equals方法
@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Man man = (Man) o;return age == man.age &&Objects.equals(name, man.name);}2. toString方法
-
toString方法默認打印的是對象的虛擬地址值。
- public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}
-
String類、包裝類、Data類、IO流等都重寫了Object類中的toString方法,使得調用此類對象的toString方法,返回對象的內容。
-
一般對于自定義的類,也想用toString方法比較兩個對象的內容是否一致,這時就需要重寫toString方法。可以用快捷鍵:Alt + insert 生成。一般是返回對象的屬性等。
toString()方法默認返回對象的字符串表示形式,也就是對象的地址,通過重寫toString()方法可以讓其返回對象的屬性等值。
二、 包裝類
1. 包裝類簡介
一般地,當需要使用數字的時候,我們通常使用內置數據類型,如:byte、int、long、double 等。但編程中經常會遇到需要使用對象,而不是內置數據類型的情形。
為了解決這個問題,Java 語言為每一個內置數據類型提供了對應的包裝類。這樣基本數據類型就也具有了類的特征。所有的包裝類**(Integer、Long、Byte、Double、Float、Short)**都是抽象類 Number 的子類。
| Boolean | boolean |
| Byte | byte |
| Short | short |
| Integer | int |
| Long | long |
| Character | char |
| Float | float |
| Double | double |
2. 包裝類、基本數據類型、String類的轉換
2.1 基本數據類型轉為包裝類
調用包裝類的構造器
public class Demo01 {public static void main(String[] args) {//基本數據類型轉換為包裝類:利用包裝類的構造器int num1 = 10;//System.out.println(num1.toString()); 報錯,因為num1是基本數據類型,不能調用類方法Integer num2 = new Integer(num1); //將num1的值作為包裝類Integer構造方法的參數,轉為包裝類對象num2System.out.println(num2.toString()); //包裝類中的toString方法也是重寫過的,輸出對象的內容Integer num3 = new Integer("123");System.out.println(num3.toString());//Integer num4 = new Integer("123abc");//System.out.println(num4.toString()); 由于數字與字母混用出現格式錯誤Float f1 = new Float(12.3f);System.out.println(f1);Float f2 = new Float("12.3f");System.out.println(f2);//Float f3 = new Float("12.3abc");//System.out.println(f3); 由于數字與字母混用出現格式錯誤Num num = new Num();System.out.println(num.b1); //當變量是boolean型時,默認值是falseSystem.out.println(num.b2); //當轉換為包裝類Boolean時,默認值是null} } class Num {boolean b1;Boolean b2; } ----------------------------------------- 運行結果:1012312.312.3falsenull2.2 包裝類轉換為基本類型
調用包裝類方法Value()
public class Demo01 {public static void main(String[] args) {Integer num1 = new Integer(12);double num2 = num1.doubleValue();System.out.println(num2 + 1);} } --------------------------------------------------- 運行結果:13.0132.3 自動裝箱與自動拆箱
上面學習了包裝類與基本數據類型之間的轉換,但是在JDK1.5之后加入了自動裝箱與自動拆箱的新特性。
一般情況下,包裝類的對象是不能進行數值運算的,但由于自動拆箱的存在,包裝類在書寫上可以和基本數據類型一樣加減乘除。
一般情況下,基本數據類型是不可能轉換為一個包裝類類型的,要借助包裝類的構造方法。但是由于自動裝箱的存在,在書寫上,也可以直接將一個數值賦給一個對象類型的。
因此,下面的書寫也是沒有問題的:
public class Demo01 {public static void main(String[] args) {int num1 = 10;Integer num2 = new Integer(20);Integer num3 = new Integer(30);//自動拆箱,包裝類對象自動轉為基本數據類型進行加減乘除System.out.println(num2 + num3);//自動封箱,基本數據類型可以賦給包裝類對象Integer num4 = num1;System.out.println(num4.toString());} } ------------------------------------------------ 運行結果:5010由于自動裝箱與自動拆箱的存在,基本數據類型與包裝類的區別就不是那么明顯了,書寫上可以看作是一個類型。
2.4 基本數據類型、包裝類轉換為String類
由于自動裝箱與自動拆箱的存在,基本數據類型與包裝類的區別就不是那么明顯了,這里將其看作一個整體實現向String類型的轉換。
使用String類里的valueOf方法;
2.5 String類轉換為基本數據類型、包裝類
使用包裝類的Paras方法
public class Demo01 {public static void main(String[] args) {//基本數據類型、包裝類轉為String類:valueOf方法float f1 = 12.3f;String s1 = String.valueOf(f1);System.out.println(s1);Double d1 = new Double(12.5);String s2 = String.valueOf(d1);System.out.println(s2);Boolean b1 = new Boolean(true);String s3 = String.valueOf(b1);System.out.println(s3);System.out.println("*****String類轉為基本數據類型、包裝類*****");//String類轉換為基本數據類型、包裝類String str1 = "123";String str2 = "123.5";//int num1 = (int)str1; 類對象不能強制轉換為基本類型//Integer num2 = (Integer)str1; 類對象要想實現強制轉換,轉換前后的類必須有父子關系Integer num1 = Integer.parseInt(str1);Double num2 = Double.parseDouble(str2);System.out.println(num1);System.out.println(num2);String str3 = "true";Boolean num3 = Boolean.parseBoolean(str3);System.out.println(num3);//對于boolean包裝類,只要不是true,都轉換為falseString str4 = "true100";Boolean num4 = Boolean.parseBoolean(str4);System.out.println(num4);} } -------------------------------------------------- 運行結果:12.312.5true*****String類轉為基本數據類型、包裝類*****123123.5truefalse3. 一個例子
public class Demo01 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j);//當數值在-128~127范圍內,自動封裝的引用指向的都是同一個對象(IntegerCache中的Integer[]數組中的值)Integer a = 20;Integer b = 20;System.out.println(a == b);//當超出范圍,自動封裝就是new一個新的對象引用,這時兩次封裝指向的就是不同的對象Integer x = 128;Integer y = 128;System.out.println(x == y);} } ----------------------------------------- 運行結果:falsetruefalse所有的包裝類內部都有一個數組用于存儲所指示范圍內的數據,因為比較常用,為了提高效率就用了這么一個數組,當自動封裝的數據為該范圍內的數值時,就直接指向數組內對應的值。
當超出數組范圍的數據時,自動封裝相當于使用new關鍵字調用包裝類的構造方法,創建一個新對象的引用,這時兩次自動封裝所指向的對象就不一樣了。
三、String類
字符串廣泛應用 在 Java 編程中,在 Java 中字符串屬于對象,Java 提供了 String 類來創建和操作字符串。
1. String類簡介
- String類是一個final類,不可被繼承
- String類實現了Serializable接口:表示字符串是支持序列化的(IO流)
- String類實現了Comparable接口:表示String可以比較大小
- String類內部定義了final char[] value數組用于存儲字符串的數據。也就是說字符串本質是一個字符數組,數組內的每一個元素都是char類型
- String代表不可變的字符序列。具有不可變性。字符串的值在創建之后不能更改。
2. 創建字符串
創建字符串有兩種方式:
- 直接創建
- String str = "automan";
- 利用構造方法創建
- String str2 = new String("automan")
這兩種方法的作用效果是不一樣的。字符串常量是存儲在方法區的常量池中的。直接創建時,String類的引用在棧中,直接指向常量池中的字符串。利用new創建時,String類引用指向堆中的String類對象,String類對象中存儲常量池中的字符串。
public class Demo01 {public static void main(String[] args) {String str1 = "automan";String str2 = "automan";System.out.println(str1 == str2);String str3 = new String("automan");String str4 = new String("automan");System.out.println(str3 == str4);System.out.println(str1 == str3);System.out.println(str2 == str4);} } ---------------------------- 運行結果:truefalsefalsefalse由上圖可見,str1和str2引用都是指向常量池中的字符串常量,地址一樣,因此==運算符結果為true,而str3存儲的時堆中String對象的地址,str4中存儲的是堆中String對象的地址,地址不一樣,因此==運算結果為false。這也是兩種String類實例化方式的區別。
同樣的,對于下面程序有:
public class Demo01 {public static void main(String[] args) {Person p1 = new Person("automan", 20);Person p2 = new Person("automan",20);Person p3 = new Person(new String("automan"), 20);System.out.println(p1.name == p2.name);System.out.println(p1.name == p3.name);} } class Person {String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;} } ----------------------------------------- 運行結果:truefalse3. 連接字符串
String 類提供了連接兩個字符串的方法:
- string1.concat(string2);:返回 string2 連接 string1 的新字符串。也可以對字符串常量使用 concat() 方法
- 更常用的是使用'+'操作符來連接字符串
不同拼接操作的比較:
public class Demo01 {public static void main(String[] args) {String s1 = "hello";String s2 = "world";String s3 = "helloworld";String s4 = "hello" + "world";String s5 = "hello" + s2;String s6 = s1 + s2;String s7 = (s1 + s2).intern();System.out.println(s3 == s4);System.out.println(s3 == s5);System.out.println(s3 == s6);System.out.println(s4 == s5);System.out.println(s3 == s7);//有final修飾的是常量,常量與常量拼接結果在常量池中。final String s8 = "world";String s9 = "hello" + s8;System.out.println(s3 == s9);} } ------------------------------------ 運行結果:truefalsefalsefalsetruetrue- 常量與常量的拼接,結果也在常量池中,且常量池中不會村次昂相同內容的常量;
- 只要有一個是變量,結果就在堆中
- 如果拼接結果調用intern()方法,則返回值是常量池中的結果。
4. 一個例子
public class Demo01 {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) {Demo01 test = new Demo01();test.change(test.str, test.ch);System.out.println(test.str);System.out.println(test.ch);} } ------------------------------ 運行結果:goodbest對于原來的存儲可以看作是這樣的,引用類型作為形參,傳遞的是地址,因此局部變量和原有變量指向的是同一個對象:
當執行change方法后:
change內的操作使得局部變量str指向的對象改變,但原來str指向的沒有改變。change內的操作使得堆里面char[]數組的的第一個元素指向改變,因此原來ch指向的char[]數組內容發生了變化。
這也是String字符串不可變性的體現
5.String類中的常用方法
| length() | 返回字符串長度 |
| boolean isEmpty() | 判斷字符串是否為空。 |
| toLowerCase() | 使用默認語言環境,將String中所有字符轉為小寫 |
| toUpperCase() | 使用默認語言環境,將String中所有字符轉為大寫 |
| concat(String str) | 將指定的字符串連接到該字符串的末尾 |
| equals(Object obj) | 將此字符串與指定對象進行比較 |
| equalsIgnoreCase(Object obj) | 將此字符串與指定對象進行比較,忽略大小寫 |
| endsWith(String suffix) | 測試字符串是否以指定后綴結束 |
| startsWith(String prefix) | 測試字符串是否以指定前綴開始 |
| startsWith(String prefix,int toffset) | 測試該字符串從指定索引開始的子字符串是否以指定前綴開始 |
| indexOf(String str) | 返回指定子字符串在該字符串中第一次出現時的索引 |
| indexOf(String str, int fromIndex) | 從指定索引開始,返回指定子字符串在該字符串中第一次出現時的索引 |
| lastIndexOf(String str) | 返回指定子字符串在該字符串中最后一次出現時的索引 |
| lastIndexOf(String str, int fromIndex) | 從指定索引開始反向搜索,返回指定子字符串在該字符串中最后一次出現時的索引 |
| contains(CharSequence s) | 當且僅當字符串中包含指定的char值序列時,返回true |
6. String與字符數組的轉換
- String轉換為字符數組
- 使用String類中的toCharArray方法
- 字符數組轉為String
- 調用String的構造器
7. String與字節數組的轉換
- String轉換為字符數組
- 使用String類中的getBytes方法
- 字符數組轉為String
- 調用String的構造器
String與字節數組的轉換經過了編碼與解碼的過程,編碼與解碼時的字符集要一致。
四、StringBuffer 和 StringBuilder 類
當對字符串進行修改的時候,需要使用 StringBuffer 和 StringBuilder 類。
1. String類、StringBuffer 和 StringBuilder 類比較
- String類: 不可變的字符序列
- StringBuffer類:可變的字符序列,線程安全,效率低
- StringBuilder類:可變的字符序列,線程不安全,效率高
- 三個類都是關于字符串的類,底層都是使用char[] 數組存儲字符串內容。
關于String類的不可變:
String字符串是不可變的字符列,有如下特點:
String str1 = "hello"; //相當于在常量池中有一個"hello",將str1指向的該字符串常量; str1 = "hello" + "world"; //這就會在常量池中新建一個"helloworld"常量,將str1引用指向這個新的字符串常量,原來的"hello"依然存在。 str1 = "mm"; //這就會在常量池中新建一個"mm"常量,將str1引用指向這個新的字符串常量,原來的"hello"和"helloworld"依然存在。 //這些留下來的字符常量就交給垃圾回收,當沒有引用指向它們時,JVM認為它們無用了就會回收釋放空間。但是 StringBuffer 和 StringBuilder 類不一樣,StringBuffer 和 StringBuilder 類的對象能夠被多次的修改,并且不產生新的未使用對象。
StringBuffer sb1 = "hello"; //相當于在常量池中有一個"hello",將sb1指向的該字符串常量; sb1 = "hello" + "world"; //還是常量池中原有的那個"hello",會在其底層的char[]數組后面加上"world",還是將sb1指向常量池中的這個字符串,但字符串內容變了。不會產生新的字符串常量。 sb1 = "mm"; //還是在常量池中的那個字符串常量,將其底層的char[]數組內的元素變為mm,不產生新的字符串常量。由此可已看出StringBuffer類的字符串長度似乎是“可變”的。
分析其源碼可以知道,StringBuffer類和StringBuilder 類當創建一個新的空對象時,其底層的char[]數組默認長度是16,也就是說相當于默認創建的是一個長度為16的數組,可以存放16個字符。
當存儲的字符串長度超過16時,就需要擴容,根據其源碼的設計,默認會新建一個長度為2 * 當前數組長度 + 2的新的字符數組,并將現有字符數組里的內容賦值給新數組。
一般情況下,應該盡量避免擴容(創建新數組并復制元素,當數據量較大時,速度較慢),因此應該預判會用到多長的數組,在創建新對象時,使用有參的構造方法確定字符串長度。此時底層的數組的長度為設定的字符串長度+16
public class Demo01 {public static void main(String[] args) {String str = new String(); //底層char[] value = new char[0];String str1 = new String("abc");//底層char[] value = new char[0]{a, b, c};StringBuffer sb1 = new StringBuffer(); //底層char[] value = new char[16];底層創建一個長度為16的數組sb1.append('a'); //底層:value[0] = 'a'; 相當于把字符依次賦給長度為16的字符數組sb1.append('b'); //底層:value[1] = 'b'; 相當于把字符依次賦給長度為16的字符數組//但此時返回字符串的長度,返回的是往數組內填充的元素的個數,而不是全部的字符數組長度System.out.println(sb1.length()); //字符串的長度為2StringBuffer sb2 = new StringBuffer("abc");//底層char[] value = new char["abc".length + 16];} }一般情況下,對于需要修改的字符串,優先選用StringBuffer 和 StringBuilder 類,而不是String類。然后再根據線程安全問題選擇是StringBuffer 還是 StringBuilder 類,并預判所需的字符串長度,調用有參的構造方法創建可變的StringBuffer對象或者 StringBuilder 對象。
2. SrtingBuffer類的常用方法
| append(xxx) | 類似于字符串拼接,再已有字符串后面填充xxx |
| delete(int start, int end) | 刪除指定區域內的字符 |
| replace(int start, int end, String str) | 替代指定范圍內的字符為str |
| insert(int offset, xxx) | 再指定位置插入xxx |
| reverse() | 把當前字符序列逆轉 |
| indexOf(String str) | 返回str再當前字符串中首次出現的位置 |
| substring(int start,int end) | 返回一個start到end的左閉右開的子字符串(切片) |
| length() | 返回字符串長度 |
| charAt(int n ) | 返回指定索引處的字符 |
| setCharAt(int n ,char ch) | 將指定位置的字符改為ch |
- 當使用append方法和insert方法時,若原有value長度不夠,可擴容。
- 上述方法都支持方法鏈操作
總結:
- 增:append(xxx)
- 刪:delete(int start, int end)
- 改:setCharAt(int n ,char ch)和replace(int start, int end, String str)
- 查:`charAt(int n )
- 插:insert(int offset, xxx)
- 長度:length()
- 遍歷:for循環 + charAt(int n )
3. StringBuilder類
StringBuilder 和StringBuffer非常類似,均代表可變的字符序列,而且提供相關功能的方法也一樣
4. 三者效率對比
public class Demo01 {public static void main(String[] args) {//初始設置long startTime = 0L;long endTime = 0L;String text = "";StringBuffer buffer = new StringBuffer("");StringBuilder builder = new StringBuilder("");//開始對比startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {buffer.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuffer的執行時間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {builder.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuilder的執行時間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {text = text + i;}endTime = System.currentTimeMillis();System.out.println("String的執行時間:" + (endTime - startTime));} } ---------------------- 運行結果;StringBuffer的執行時間:5StringBuilder的執行時間:3String的執行時間:1493轉載
總結
以上是生活随笔為你收集整理的JavaSE基础——常用类1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: タイトル キャッスルファンタジア ~エレ
- 下一篇: Ardunio开发实例-VL53L0X飞