日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

JavaSE基础——常用类1

發(fā)布時(shí)間:2023/12/20 java 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaSE基础——常用类1 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JavaSE基礎(chǔ)——常用類1

一、Object類

java.lang.Object類是Java語(yǔ)言中的根類,即所有類的父類。它當(dāng)中描述的所有方法子類都可以使用。

如果在類的聲明中沒(méi)有顯式地使用extends來(lái)指明父類,則該類默認(rèn)的父類就是java.lang.Object。

根據(jù)API文檔,Object類中包含的方法有11個(gè):

  • toString()方法、equals()方法:詳細(xì)說(shuō)明

  • hashCode()方法:返回對(duì)象的哈希碼值。(集合

  • clone()方法:創(chuàng)建并返回對(duì)象的副本。

  • getclass()方法

    :返回對(duì)象所在的類。

    • ``getclass().getSuperclass()方法`:返回對(duì)象所在的父類
  • finalize()方法:當(dāng)垃圾收集確定不再有對(duì)該對(duì)象的引用時(shí),垃圾收集器在對(duì)象上調(diào)用該方法。

    • 垃圾回收機(jī)制只回收J(rèn)VM堆內(nèi)存里的對(duì)象空間。對(duì)其他類如數(shù)據(jù)庫(kù)連接、輸入輸出流、Socket連接等無(wú)能為力。
    • 垃圾回收具有不可預(yù)知性,程序無(wú)法精準(zhǔn)控制垃圾回收機(jī)制的執(zhí)行。程序員可以通過(guò)System.gc()或者Runtime.getRuntime.gc()來(lái)通知系統(tǒng)進(jìn)行垃圾回收,但系統(tǒng)什么時(shí)候進(jìn)行不得而知
    • 垃圾回收機(jī)制回收任何對(duì)象前,總會(huì)讓對(duì)象調(diào)用自身的finalize()方法。
    • 可以將對(duì)象的引用變量設(shè)為null,來(lái)表明需要垃圾回收機(jī)制回收該對(duì)象。
  • notify()方法、 notifyAll()方法、 wait()方法(3個(gè)):(線程

下面學(xué)習(xí)幾個(gè)主要的方法:

1. equals方法

1.1 ==運(yùn)算符回顧

  • ==是運(yùn)算符,可以使用在基本數(shù)據(jù)類型和引用類型的比較
  • 如果比較的是基本數(shù)據(jù)類型,則比較這兩個(gè)變量保存的值是否相等,此時(shí)與數(shù)據(jù)類型無(wú)關(guān)。比如:char類型的10和int類型的10是相等的,因?yàn)樗麄兊闹迪嗟取?/li>
  • 如果比較的是引用類型,則比較的是引用的地址值是否相等。即比較兩個(gè)引用是否指向同一個(gè)對(duì)象

1.2 equals方法

  • equals()是一個(gè)方法,只能被對(duì)象調(diào)用,因此只能用于引用類型的比較
  • Object類中的equals()方法和==運(yùn)算符的作用是相同的,即都是比較引用的地址值是否相同,判斷是否指向同一個(gè)對(duì)象
  • String類、包裝類、Data類、IO流等都重寫了Object類中的equals方法,重寫后都是比較兩個(gè)對(duì)象的內(nèi)容是否相同。
// == 與 equals方法 public class Demo01 {public static void main(String[] args) {// == 運(yùn)算符用于數(shù)值類型的比較時(shí),比較兩個(gè)對(duì)象存儲(chǔ)的值是否相等//注意不能比較boolean值int a = 65;double b= 65.0;char c = 65;char d = 'A';boolean e = true;int f = 1;System.out.println(a == b);System.out.println(a == c);System.out.println(a == d);System.out.println(c == d);//即使數(shù)據(jù)類型不一致,但由于變量中存儲(chǔ)的值時(shí)相同的,因此結(jié)果都是true//System.out.println(e == f); 直接報(bào)錯(cuò),== 不能比較boolean類型和其他數(shù)據(jù)類型System.out.println("************ == 用于引用類型的比較***********");// == 用于引用類型的比較時(shí),比較兩個(gè)引用的地址是否一樣,即比較兩個(gè)引用是否指向同一個(gè)對(duì)象;String s = new String("automan");String s1 = new String("automan");System.out.println(s == s1);Man man = new Man("張三",20);Man man1 = new Man("張三",20);Man man2 = man;System.out.println(man == man1);System.out.println(man == man2);System.out.println("************ equals方法用于引用類型的比較***********");//Object類中的equals方法System.out.println("Object類中的equals:" + man.equals(man1));//String類中的equals方法System.out.println("String類中的equals:" + s.equals(s1));} } class Man {String name;int age;public Man() {}public Man(String name, int age) {this.name = name;this.age = age;} } --------------------------------------------------- 運(yùn)行結(jié)果:truetruetruetrue*********** == 用于引用類型的比較**********falsefalsetrue********** equals方法用于引用類型的比較*********Object類中的equals:falseString類中的equals:true

1.3 equals方法的重寫

一般對(duì)于自定義的類,也想用equals方法比較兩個(gè)對(duì)象的內(nèi)容是否一致,這時(shí)就需要重寫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方法默認(rèn)打印的是對(duì)象的虛擬地址值。

    • public String toString() {return getClass().getName() + "@" + Integer.toHexString(hashCode());}
  • String類、包裝類、Data類、IO流等都重寫了Object類中的toString方法,使得調(diào)用此類對(duì)象的toString方法,返回對(duì)象的內(nèi)容。

  • 一般對(duì)于自定義的類,也想用toString方法比較兩個(gè)對(duì)象的內(nèi)容是否一致,這時(shí)就需要重寫toString方法。可以用快捷鍵:Alt + insert 生成。一般是返回對(duì)象的屬性等。

import java.util.Date; public class Demo01 {public static void main(String[] args) {Man man = new Man("張三",20);System.out.println(man);System.out.println(man.toString());System.out.println("***************");String s = "automan";System.out.println(s);System.out.println(s.toString());System.out.println("***************");Date date = new Date(456487985695L);System.out.println(date);System.out.println(date.toString());} } class Man {String name;int age;public Man() {}public Man(String name, int age) {this.name = name;this.age = age;} } -------------------------------------------------- 運(yùn)行結(jié)果:com.CommomMethod.www.Man@14ae5a5com.CommomMethod.www.Man@14ae5a5***************automanautoman***************Tue Jun 19 18:13:05 CST 1984Tue Jun 19 18:13:05 CST 1984//可以看到打印對(duì)象名,實(shí)際上也就是在調(diào)用對(duì)象的toString方法。

toString()方法默認(rèn)返回對(duì)象的字符串表示形式,也就是對(duì)象的地址,通過(guò)重寫toString()方法可以讓其返回對(duì)象的屬性等值。

二、 包裝類

1. 包裝類簡(jiǎn)介

一般地,當(dāng)需要使用數(shù)字的時(shí)候,我們通常使用內(nèi)置數(shù)據(jù)類型,如:byte、int、long、double 等。但編程中經(jīng)常會(huì)遇到需要使用對(duì)象,而不是內(nèi)置數(shù)據(jù)類型的情形。

為了解決這個(gè)問(wèn)題,Java 語(yǔ)言為每一個(gè)內(nèi)置數(shù)據(jù)類型提供了對(duì)應(yīng)的包裝類。這樣基本數(shù)據(jù)類型就也具有了類的特征。所有的包裝類**(Integer、Long、Byte、Double、Float、Short)**都是抽象類 Number 的子類。

包裝類基本數(shù)據(jù)類型
Booleanboolean
Bytebyte
Shortshort
Integerint
Longlong
Characterchar
Floatfloat
Doubledouble

public class Demo01 {public static void main(String[] args) {// 此時(shí)自動(dòng)調(diào)用:Integer.valueOf(),若數(shù)字大于-128且小于127,直接返回值,否則新建一個(gè)對(duì)象Integer integer1 = 1000;Integer integer2 = 1000;int i1 = 1000;int i2 = 1000;// 因?yàn)閮蓚€(gè)變量不是同一個(gè)對(duì)象因此結(jié)果為falseSystem.out.println(integer1 == integer2); System.out.println(integer1.equals(integer2));// trueSystem.out.println(i1 == i2); // trueSystem.out.println(i1 == integer2); // true} } --------------------------------------------------- 運(yùn)行結(jié)果:falsetruetruetrue //包裝類后也具有類的特征了

2. 包裝類、基本數(shù)據(jù)類型、String類的轉(zhuǎn)換

2.1 基本數(shù)據(jù)類型轉(zhuǎn)為包裝類

調(diào)用包裝類的構(gòu)造器

public class Demo01 {public static void main(String[] args) {//基本數(shù)據(jù)類型轉(zhuǎn)換為包裝類:利用包裝類的構(gòu)造器int num1 = 10;//System.out.println(num1.toString()); 報(bào)錯(cuò),因?yàn)閚um1是基本數(shù)據(jù)類型,不能調(diào)用類方法Integer num2 = new Integer(num1); //將num1的值作為包裝類Integer構(gòu)造方法的參數(shù),轉(zhuǎn)為包裝類對(duì)象num2System.out.println(num2.toString()); //包裝類中的toString方法也是重寫過(guò)的,輸出對(duì)象的內(nèi)容Integer num3 = new Integer("123");System.out.println(num3.toString());//Integer num4 = new Integer("123abc");//System.out.println(num4.toString()); 由于數(shù)字與字母混用出現(xiàn)格式錯(cuò)誤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); 由于數(shù)字與字母混用出現(xiàn)格式錯(cuò)誤Num num = new Num();System.out.println(num.b1); //當(dāng)變量是boolean型時(shí),默認(rèn)值是falseSystem.out.println(num.b2); //當(dāng)轉(zhuǎn)換為包裝類Boolean時(shí),默認(rèn)值是null} } class Num {boolean b1;Boolean b2; } ----------------------------------------- 運(yùn)行結(jié)果:1012312.312.3falsenull

2.2 包裝類轉(zhuǎn)換為基本類型

調(diào)用包裝類方法Value()

public class Demo01 {public static void main(String[] args) {Integer num1 = new Integer(12);double num2 = num1.doubleValue();System.out.println(num2 + 1);} } --------------------------------------------------- 運(yùn)行結(jié)果:13.013

2.3 自動(dòng)裝箱與自動(dòng)拆箱

上面學(xué)習(xí)了包裝類與基本數(shù)據(jù)類型之間的轉(zhuǎn)換,但是在JDK1.5之后加入了自動(dòng)裝箱與自動(dòng)拆箱的新特性。

一般情況下,包裝類的對(duì)象是不能進(jìn)行數(shù)值運(yùn)算的,但由于自動(dòng)拆箱的存在,包裝類在書寫上可以和基本數(shù)據(jù)類型一樣加減乘除。

一般情況下,基本數(shù)據(jù)類型是不可能轉(zhuǎn)換為一個(gè)包裝類類型的,要借助包裝類的構(gòu)造方法。但是由于自動(dòng)裝箱的存在,在書寫上,也可以直接將一個(gè)數(shù)值賦給一個(gè)對(duì)象類型的。

因此,下面的書寫也是沒(méi)有問(wèn)題的:

public class Demo01 {public static void main(String[] args) {int num1 = 10;Integer num2 = new Integer(20);Integer num3 = new Integer(30);//自動(dòng)拆箱,包裝類對(duì)象自動(dòng)轉(zhuǎn)為基本數(shù)據(jù)類型進(jìn)行加減乘除System.out.println(num2 + num3);//自動(dòng)封箱,基本數(shù)據(jù)類型可以賦給包裝類對(duì)象Integer num4 = num1;System.out.println(num4.toString());} } ------------------------------------------------ 運(yùn)行結(jié)果:5010

由于自動(dòng)裝箱與自動(dòng)拆箱的存在,基本數(shù)據(jù)類型與包裝類的區(qū)別就不是那么明顯了,書寫上可以看作是一個(gè)類型。

2.4 基本數(shù)據(jù)類型、包裝類轉(zhuǎn)換為String類

由于自動(dòng)裝箱與自動(dòng)拆箱的存在,基本數(shù)據(jù)類型與包裝類的區(qū)別就不是那么明顯了,這里將其看作一個(gè)整體實(shí)現(xiàn)向String類型的轉(zhuǎn)換。

使用String類里的valueOf方法;

2.5 String類轉(zhuǎn)換為基本數(shù)據(jù)類型、包裝類

使用包裝類的Paras方法

public class Demo01 {public static void main(String[] args) {//基本數(shù)據(jù)類型、包裝類轉(zhuǎn)為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類轉(zhuǎn)為基本數(shù)據(jù)類型、包裝類*****");//String類轉(zhuǎn)換為基本數(shù)據(jù)類型、包裝類String str1 = "123";String str2 = "123.5";//int num1 = (int)str1; 類對(duì)象不能強(qiáng)制轉(zhuǎn)換為基本類型//Integer num2 = (Integer)str1; 類對(duì)象要想實(shí)現(xiàn)強(qiáng)制轉(zhuǎn)換,轉(zhuǎn)換前后的類必須有父子關(guān)系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);//對(duì)于boolean包裝類,只要不是true,都轉(zhuǎn)換為falseString str4 = "true100";Boolean num4 = Boolean.parseBoolean(str4);System.out.println(num4);} } -------------------------------------------------- 運(yùn)行結(jié)果:12.312.5true*****String類轉(zhuǎn)為基本數(shù)據(jù)類型、包裝類*****123123.5truefalse

3. 一個(gè)例子

public class Demo01 {public static void main(String[] args) {Integer i = new Integer(1);Integer j = new Integer(1);System.out.println(i == j);//當(dāng)數(shù)值在-128~127范圍內(nèi),自動(dòng)封裝的引用指向的都是同一個(gè)對(duì)象(IntegerCache中的Integer[]數(shù)組中的值)Integer a = 20;Integer b = 20;System.out.println(a == b);//當(dāng)超出范圍,自動(dòng)封裝就是new一個(gè)新的對(duì)象引用,這時(shí)兩次封裝指向的就是不同的對(duì)象Integer x = 128;Integer y = 128;System.out.println(x == y);} } ----------------------------------------- 運(yùn)行結(jié)果:falsetruefalse

所有的包裝類內(nèi)部都有一個(gè)數(shù)組用于存儲(chǔ)所指示范圍內(nèi)的數(shù)據(jù),因?yàn)楸容^常用,為了提高效率就用了這么一個(gè)數(shù)組,當(dāng)自動(dòng)封裝的數(shù)據(jù)為該范圍內(nèi)的數(shù)值時(shí),就直接指向數(shù)組內(nèi)對(duì)應(yīng)的值。

當(dāng)超出數(shù)組范圍的數(shù)據(jù)時(shí),自動(dòng)封裝相當(dāng)于使用new關(guān)鍵字調(diào)用包裝類的構(gòu)造方法,創(chuàng)建一個(gè)新對(duì)象的引用,這時(shí)兩次自動(dòng)封裝所指向的對(duì)象就不一樣了。

三、String類

字符串廣泛應(yīng)用 在 Java 編程中,在 Java 中字符串屬于對(duì)象,Java 提供了 String 類來(lái)創(chuàng)建和操作字符串。

1. String類簡(jiǎn)介

  • String類是一個(gè)final類,不可被繼承
  • String類實(shí)現(xiàn)了Serializable接口:表示字符串是支持序列化的(IO流)
  • String類實(shí)現(xiàn)了Comparable接口:表示String可以比較大小
  • String類內(nèi)部定義了final char[] value數(shù)組用于存儲(chǔ)字符串的數(shù)據(jù)。也就是說(shuō)字符串本質(zhì)是一個(gè)字符數(shù)組,數(shù)組內(nèi)的每一個(gè)元素都是char類型
  • String代表不可變的字符序列。具有不可變性。字符串的值在創(chuàng)建之后不能更改。

2. 創(chuàng)建字符串

創(chuàng)建字符串有兩種方式:

  • 直接創(chuàng)建
    • String str = "automan";
  • 利用構(gòu)造方法創(chuàng)建
    • String str2 = new String("automan")

這兩種方法的作用效果是不一樣的。字符串常量是存儲(chǔ)在方法區(qū)的常量池中的。直接創(chuàng)建時(shí),String類的引用在棧中,直接指向常量池中的字符串。利用new創(chuàng)建時(shí),String類引用指向堆中的String類對(duì)象,String類對(duì)象中存儲(chǔ)常量池中的字符串。

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);} } ---------------------------- 運(yùn)行結(jié)果:truefalsefalsefalse

由上圖可見(jiàn),str1和str2引用都是指向常量池中的字符串常量,地址一樣,因此==運(yùn)算符結(jié)果為true,而str3存儲(chǔ)的時(shí)堆中String對(duì)象的地址,str4中存儲(chǔ)的是堆中String對(duì)象的地址,地址不一樣,因此==運(yùn)算結(jié)果為false。這也是兩種String類實(shí)例化方式的區(qū)別。

同樣的,對(duì)于下面程序有:

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;} } ----------------------------------------- 運(yùn)行結(jié)果:truefalse

3. 連接字符串

String 類提供了連接兩個(gè)字符串的方法:

  • string1.concat(string2);:返回 string2 連接 string1 的新字符串。也可以對(duì)字符串常量使用 concat() 方法
  • 更常用的是使用'+'操作符來(lái)連接字符串

不同拼接操作的比較

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修飾的是常量,常量與常量拼接結(jié)果在常量池中。final String s8 = "world";String s9 = "hello" + s8;System.out.println(s3 == s9);} } ------------------------------------ 運(yùn)行結(jié)果:truefalsefalsefalsetruetrue
  • 常量與常量的拼接,結(jié)果也在常量池中,且常量池中不會(huì)村次昂相同內(nèi)容的常量;
  • 只要有一個(gè)是變量,結(jié)果就在堆中
  • 如果拼接結(jié)果調(diào)用intern()方法,則返回值是常量池中的結(jié)果。

4. 一個(gè)例子

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);} } ------------------------------ 運(yùn)行結(jié)果:goodbest

對(duì)于原來(lái)的存儲(chǔ)可以看作是這樣的,引用類型作為形參,傳遞的是地址,因此局部變量和原有變量指向的是同一個(gè)對(duì)象

當(dāng)執(zhí)行change方法后:

change內(nèi)的操作使得局部變量str指向的對(duì)象改變,但原來(lái)str指向的沒(méi)有改變。change內(nèi)的操作使得堆里面char[]數(shù)組的的第一個(gè)元素指向改變,因此原來(lái)ch指向的char[]數(shù)組內(nèi)容發(fā)生了變化。

這也是String字符串不可變性的體現(xiàn)

5.String類中的常用方法

常用方法作用
length()返回字符串長(zhǎng)度
boolean isEmpty()判斷字符串是否為空。
toLowerCase()使用默認(rèn)語(yǔ)言環(huán)境,將String中所有字符轉(zhuǎn)為小寫
toUpperCase()使用默認(rèn)語(yǔ)言環(huán)境,將String中所有字符轉(zhuǎn)為大寫
concat(String str)將指定的字符串連接到該字符串的末尾
equals(Object obj)將此字符串與指定對(duì)象進(jìn)行比較
equalsIgnoreCase(Object obj)將此字符串與指定對(duì)象進(jìn)行比較,忽略大小寫
endsWith(String suffix)測(cè)試字符串是否以指定后綴結(jié)束
startsWith(String prefix)測(cè)試字符串是否以指定前綴開(kāi)始
startsWith(String prefix,int toffset)測(cè)試該字符串從指定索引開(kāi)始的子字符串是否以指定前綴開(kāi)始
indexOf(String str)返回指定子字符串在該字符串中第一次出現(xiàn)時(shí)的索引
indexOf(String str, int fromIndex)從指定索引開(kāi)始,返回指定子字符串在該字符串中第一次出現(xiàn)時(shí)的索引
lastIndexOf(String str)返回指定子字符串在該字符串中最后一次出現(xiàn)時(shí)的索引
lastIndexOf(String str, int fromIndex)從指定索引開(kāi)始反向搜索,返回指定子字符串在該字符串中最后一次出現(xiàn)時(shí)的索引
contains(CharSequence s)當(dāng)且僅當(dāng)字符串中包含指定的char值序列時(shí),返回true

6. String與字符數(shù)組的轉(zhuǎn)換

  • String轉(zhuǎn)換為字符數(shù)組
    • 使用String類中的toCharArray方法
  • 字符數(shù)組轉(zhuǎn)為String
    • 調(diào)用String的構(gòu)造器
//將一個(gè)字符串進(jìn)行反轉(zhuǎn)。將字符串中指定部分進(jìn)行反轉(zhuǎn)。比如將“abcdefg”反轉(zhuǎn)為”abfedcg” public class Demo01 {public static void main(String[] args) {String str = "a21cb3";//此處給定的值是字符數(shù)組的索引值System.out.println(reverse(str,1,4));}public static String reverse(String str, int begin, int end) {if (str != null) {char[] ch = str.toCharArray();for (int i = begin, j = end; i < j; i++, j--) {char temp = ch[i];ch[i] = ch[j];ch [j] = temp;}return new String(ch);}return null;} } -------------------------------------- 運(yùn)行結(jié)果:abc123

7. String與字節(jié)數(shù)組的轉(zhuǎn)換

  • String轉(zhuǎn)換為字符數(shù)組
    • 使用String類中的getBytes方法
  • 字符數(shù)組轉(zhuǎn)為String
    • 調(diào)用String的構(gòu)造器
public class Demo01 {public static void main(String[] args) {String str1 = "abc123中國(guó)";//使用默認(rèn)的字符集進(jìn)行轉(zhuǎn)換,這里默認(rèn)的是UTF-8編碼集byte[] b = str1.getBytes();System.out.println(Arrays.toString(b));String s = new String(b);System.out.println(s);} } ------------------------------------------ 運(yùn)行結(jié)果:[97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67]abc123中國(guó)//對(duì)于漢字,UTF-8編碼用三個(gè)字節(jié)表示一個(gè)漢字

String與字節(jié)數(shù)組的轉(zhuǎn)換經(jīng)過(guò)了編碼與解碼的過(guò)程,編碼與解碼時(shí)的字符集要一致。

四、StringBuffer 和 StringBuilder 類

當(dāng)對(duì)字符串進(jìn)行修改的時(shí)候,需要使用 StringBuffer 和 StringBuilder 類。

1. String類、StringBuffer 和 StringBuilder 類比較

  • String類: 不可變的字符序列
  • StringBuffer類:可變的字符序列,線程安全,效率低
  • StringBuilder類:可變的字符序列,線程不安全,效率高
  • 三個(gè)類都是關(guān)于字符串的類,底層都是使用char[] 數(shù)組存儲(chǔ)字符串內(nèi)容。

關(guān)于String類的不可變:

String字符串是不可變的字符列,有如下特點(diǎn):

String str1 = "hello"; //相當(dāng)于在常量池中有一個(gè)"hello",將str1指向的該字符串常量; str1 = "hello" + "world"; //這就會(huì)在常量池中新建一個(gè)"helloworld"常量,將str1引用指向這個(gè)新的字符串常量,原來(lái)的"hello"依然存在。 str1 = "mm"; //這就會(huì)在常量池中新建一個(gè)"mm"常量,將str1引用指向這個(gè)新的字符串常量,原來(lái)的"hello"和"helloworld"依然存在。 //這些留下來(lái)的字符常量就交給垃圾回收,當(dāng)沒(méi)有引用指向它們時(shí),JVM認(rèn)為它們無(wú)用了就會(huì)回收釋放空間。

但是 StringBuffer 和 StringBuilder 類不一樣,StringBuffer 和 StringBuilder 類的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象

StringBuffer sb1 = "hello"; //相當(dāng)于在常量池中有一個(gè)"hello",將sb1指向的該字符串常量; sb1 = "hello" + "world"; //還是常量池中原有的那個(gè)"hello",會(huì)在其底層的char[]數(shù)組后面加上"world",還是將sb1指向常量池中的這個(gè)字符串,但字符串內(nèi)容變了。不會(huì)產(chǎn)生新的字符串常量。 sb1 = "mm"; //還是在常量池中的那個(gè)字符串常量,將其底層的char[]數(shù)組內(nèi)的元素變?yōu)閙m,不產(chǎn)生新的字符串常量。

由此可已看出StringBuffer類的字符串長(zhǎng)度似乎是“可變”的

分析其源碼可以知道,StringBuffer類和StringBuilder 類當(dāng)創(chuàng)建一個(gè)新的空對(duì)象時(shí),其底層的char[]數(shù)組默認(rèn)長(zhǎng)度是16,也就是說(shuō)相當(dāng)于默認(rèn)創(chuàng)建的是一個(gè)長(zhǎng)度為16的數(shù)組,可以存放16個(gè)字符。

當(dāng)存儲(chǔ)的字符串長(zhǎng)度超過(guò)16時(shí),就需要擴(kuò)容,根據(jù)其源碼的設(shè)計(jì),默認(rèn)會(huì)新建一個(gè)長(zhǎng)度為2 * 當(dāng)前數(shù)組長(zhǎng)度 + 2的新的字符數(shù)組,并將現(xiàn)有字符數(shù)組里的內(nèi)容賦值給新數(shù)組。

一般情況下,應(yīng)該盡量避免擴(kuò)容(創(chuàng)建新數(shù)組并復(fù)制元素,當(dāng)數(shù)據(jù)量較大時(shí),速度較慢),因此應(yīng)該預(yù)判會(huì)用到多長(zhǎng)的數(shù)組,在創(chuàng)建新對(duì)象時(shí),使用有參的構(gòu)造方法確定字符串長(zhǎng)度。此時(shí)底層的數(shù)組的長(zhǎng)度為設(shè)定的字符串長(zhǎng)度+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];底層創(chuàng)建一個(gè)長(zhǎng)度為16的數(shù)組sb1.append('a'); //底層:value[0] = 'a'; 相當(dāng)于把字符依次賦給長(zhǎng)度為16的字符數(shù)組sb1.append('b'); //底層:value[1] = 'b'; 相當(dāng)于把字符依次賦給長(zhǎng)度為16的字符數(shù)組//但此時(shí)返回字符串的長(zhǎng)度,返回的是往數(shù)組內(nèi)填充的元素的個(gè)數(shù),而不是全部的字符數(shù)組長(zhǎng)度System.out.println(sb1.length()); //字符串的長(zhǎng)度為2StringBuffer sb2 = new StringBuffer("abc");//底層char[] value = new char["abc".length + 16];} }

一般情況下,對(duì)于需要修改的字符串,優(yōu)先選用StringBuffer 和 StringBuilder 類,而不是String類。然后再根據(jù)線程安全問(wèn)題選擇是StringBuffer 還是 StringBuilder 類,并預(yù)判所需的字符串長(zhǎng)度,調(diào)用有參的構(gòu)造方法創(chuàng)建可變的StringBuffer對(duì)象或者 StringBuilder 對(duì)象。

2. SrtingBuffer類的常用方法

方法作用
append(xxx)類似于字符串拼接,再已有字符串后面填充xxx
delete(int start, int end)刪除指定區(qū)域內(nèi)的字符
replace(int start, int end, String str)替代指定范圍內(nèi)的字符為str
insert(int offset, xxx)再指定位置插入xxx
reverse()把當(dāng)前字符序列逆轉(zhuǎn)
indexOf(String str)返回str再當(dāng)前字符串中首次出現(xiàn)的位置
substring(int start,int end)返回一個(gè)start到end的左閉右開(kāi)的子字符串(切片)
length()返回字符串長(zhǎng)度
charAt(int n )返回指定索引處的字符
setCharAt(int n ,char ch)將指定位置的字符改為ch
  • 當(dāng)使用append方法和insert方法時(shí),若原有value長(zhǎng)度不夠,可擴(kuò)容。
  • 上述方法都支持方法鏈操作

總結(jié):

  • 增: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)
  • 長(zhǎng)度:length()
  • 遍歷:for循環(huán) + charAt(int n )

3. StringBuilder類

StringBuilder 和StringBuffer非常類似,均代表可變的字符序列,而且提供相關(guān)功能的方法也一樣

4. 三者效率對(duì)比

public class Demo01 {public static void main(String[] args) {//初始設(shè)置long startTime = 0L;long endTime = 0L;String text = "";StringBuffer buffer = new StringBuffer("");StringBuilder builder = new StringBuilder("");//開(kāi)始對(duì)比startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {buffer.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuffer的執(zhí)行時(shí)間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {builder.append(String.valueOf(i));}endTime = System.currentTimeMillis();System.out.println("StringBuilder的執(zhí)行時(shí)間:" + (endTime - startTime));startTime = System.currentTimeMillis();for (int i = 0; i < 20000; i++) {text = text + i;}endTime = System.currentTimeMillis();System.out.println("String的執(zhí)行時(shí)間:" + (endTime - startTime));} } ---------------------- 運(yùn)行結(jié)果;StringBuffer的執(zhí)行時(shí)間:5StringBuilder的執(zhí)行時(shí)間:3String的執(zhí)行時(shí)間:1493

轉(zhuǎn)載

總結(jié)

以上是生活随笔為你收集整理的JavaSE基础——常用类1的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。