天天看點

java進階第二講-數組、String類java進階第二講-數組、String類

java進階第二講-數組、String類

1 回顧一下Object

Object中的方法:
	public native int hashCode();
	帶有native關鍵字的方法調用的是底層C++的dll檔案
    這種方法我們在工具中看不到具體的實作,當然也可以去其他地方找相關的實作代碼。
    hashCode()它是一個對象在堆中的記憶體位址經過hash算法計算之後又進行了進制的轉換得出的結果.傳回值是int
    問題:如果兩個對象的hashCode()值一樣,說明什麼問題?是同一個對象
    hashCode()方法有什麼用?
        因為hashCode()方法計算的對象是記憶體位址,記憶體位址對于一個對象來講是惟一的,是以hashCode()算法算出來的也是唯一值。是以這個方法可以判斷:
        1. 一個對象是否存在。
        2. 一個對象與另一個對象是否是同一個對象。
        3. 兩個對象的hashCode值比較的話,就相當于引用之間使用"==",隻能比較位址,不能比較值。
        
      protected void finalize() throws Throwable { }
Called by the garbage collector on an object 
when garbage collection determines that there are no more references to the object.
    // 當GC發現沒有任何的引用指向目前對象的時候,這個方法就會被GC自動調用
    // 這個方法被調用的時候,對象被回收了嗎?還沒有,也就是說,對象在被GC回收之前,
    // GC會自動調用這個finalize()方法
    這個方法其實就是SUN公司java工程師為程式員準備的一個對象銷毀之前的時刻。可以直覺的觀測對象銷毀之前的狀态。
           
public class AarrayTest01 {

    @Override
    protected void finalize() throws Throwable {
        System.out.println("對象即将被GC回收!");
    }

    public static void main(String[] args) throws Throwable {
        Object o = new Object();
        // 翻看源碼,回到上一次停留的地方ctr + alt + ←
        System.out.println(o.hashCode());

        Object o1 = new Object();
        // 翻看源碼,回到上一次停留的地方ctr + alt + ←
        System.out.println(o1.hashCode());
        AarrayTest01 a = new AarrayTest01();
        for (int i = 0; i < 100000; i++) {
            System.out.println(new AarrayTest01());
        }
    }
}
           

2 數組

  • 聲明:declare 在java中隻能聲明一個變量,也就是說沒有給這個變量賦初始值。
  • 定義:define 在java中,定義一個變量,就是給變量指派的過程
int[] a = {1,2}; // 推薦這種方式,這種格式更有利于了解數組
int a1[];// 這種方式也行,API中大部分是這種格式
           
public class AarrayTest01 {

    public static void main(String[] args) throws Throwable {
        // 數組
        int[] a = {1,2}; // 推薦這種方式,這種格式更有利于了解數組
        int a1[];// 這種方式也行,API中大部分是這種格式

        System.out.println(a);
        // 什麼結果?記憶體中的首位址,什麼形式呢?
        // [[email protected]類型名 + @ + 記憶體位址hash後的十六進制表示
        // [[email protected] 格式其實是Object對象的toString()執行之後才會得到的結果
        // System.out.println(a);它自動調用了Objcet的toString()方法
        // 為什麼數組會自動調用Object類的toString方法?說明數組也是引用類型的。
        // 它的父類是Object。隻有這種解釋。
        // 什麼是引用類型? 類型 變量名,這個變量名指向的是一塊記憶體空間,我們說它就是引用類型。
        // A a = 記憶體位址; 這種形式就是引用類型。java當中,隻有兩種類型,基礎資料類型和引用類型
        // 引用類型所指向的記憶體位址實際是對象(常量、static修飾的變量)的記憶體位址。
        // 這也說明了,數組是引用類型。我們也可以推斷,數組的本身是儲存在堆中的。
    }
}

           
  • Object類的簡介
/**
 * Class {@code Object} is the root of the class hierarchy.
 * Every class has {@code Object} as a superclass. All objects,
 * including arrays, implement the methods of this class.
 */
           
  • 數組是一種資料類型,但是它不是基礎資料類型,是引用資料類型。
  • 基礎資料類型:byte short int long float double boolean char
  • 除去這8中之外,全是引用類型。
public class AarrayTest01 {

    public static void main(String[] args) throws Throwable {
        // 數組
        int[] a = {1,2}; // 推薦這種方式,這種格式更有利于了解數組
        int a1[];// 這種方式也行,API中大部分是這種格式

        System.out.println(a.getClass().getName());
        // a.getClass()後為什麼可以直接"."getName():因為getClass()傳回了引用(一個對象的引用)
        // 為什麼傳回的是引用,而不是對象?
        // 因為對象在堆中,很大,引用隻是一個位址,很小,從效率上來講,你說是傳引用還是傳對象?
        // 我們一般講傳輸,都是要通過網絡、通過電腦中的bus,
        // 傳一個幾個Byte資料好,還是傳幾百M上G的資料好呢?---傳引用更好
        // 好比,你在銀行有1個億的存款,你去取錢,是拿一張有一個億的卡好呢,還是拿1億的現金?
        // 你要拿1億現金,家裡先得修一個裝得下1億現金的金庫。如果你拿一張卡,就是拿了一個引用
        // 這個引用指向的是銀行的金庫,自己沒有必要再修一個金庫。
        // 在java中,基礎資料類型都是傳值
        // 引用資料都是傳引用(這裡的傳:實參和形參之間的傳遞方式,方法的傳回值傳回的方式)
        // java做好了封裝,引用類型都是傳遞的都是引用。傳回值類型也都是引用,沒有傳回過值。
        // 在C中C++中,可以傳值,也就是說可以傳指針所指向的記憶體位址的值。但這樣不好。
        // 你想,你傳一個值出來,其實是做了一份拷貝,那麼你就一定要有一塊同等大小的空間去接。
        // 浪費空間。由于值可能很大,傳輸上耗時,效率低下。
        // 誰能"."?"類名."和"引用.","類名."靜态的屬性或者是方法;"引用."成員屬性或者是方法
        // 一個方法的傳回值類型有哪些?void 基礎資料類型 引用資料類型
        // 基礎資料類型可以"."方法嗎?不能的。void傳回的是null,null也是一個引用類型
        // 它不能"."任何東西,一旦"."就會報NullPointerException
        // 能"."成員方法的隻有引用類型。
    }
}

           
  • 通過實驗,我們看到了數組擁有Object類中所有的方法。是以我們也能斷定它是Object的子類,數組也是引用類型。數組的引用如果被置空,也會報空指針異常。
  • 數組有一個屬性:length
    • length屬性,指的是數組的長度。
    • 任何一個數組都有這個屬性。

2.1 數組的類型

  • 基礎資料類型的數組:int[] a;這意味着,a所指向的數組中儲存的是int類型的資料
  • 引用類型的數組:Person[] p;這意味着,p所指向的數組中儲存的是Person類型的對象的引用。

2.2 數組的定義

  • 靜态初始化
    • int[] a = {1,2,3,4};
  • 動态初始化
    • int[] a = new int[大小];
    • 然後再給數組中的元素指派。

2.3 通路數組中元素的方式

  • 取下标的方式進行通路,下标從0開始到length-1
  • 注意:在java中,“=” 後面的大括号中的内容就是一個對象,在javascript中也是這樣。
  • 這種用法,目前來說隻對數組成立。數組指派的時候,int[] a = {……};這是靜态的初始化方式

2.4 數組的記憶體圖

java進階第二講-數組、String類java進階第二講-數組、String類

2.5 兩種初始化方式的差别

  • 靜态初始化是在已知數組元素值的時候,可以直接靜态初始化。
  • 靜态初始的時候,實際上是根據{}中的值的個數來配置設定了數組的記憶體空間
  • 動态初始化的時候,實際上是根據new int[初始化大小]中的初始化大小的值來配置設定記憶體空間
  • 動态初始化是指,後續可以給數組中的元素進行指派。
  • 如果是靜态初始化,一開始初始化的時候在{}中沒有給值,如果在後續指派,會抛出Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0。數組索引越界異常。為什麼?因為靜态初始化的時候,JVM會根據{}中的值的個數在堆中給數組配置設定大小。
  • 這也說明一個問題,一旦數組的大小被确定之後,是不能改變的。
int[] arr = {};
arr[0] = 1;
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
int[] arr1 = new int[3];
arr1[3] = 100;//ArrayIndexOutOfBoundsException: 3
           
  • 數組一旦被建立,其大小就固定了,無論靜态的還是動态的。大小是固定的。數組的大小是不可以被改變的。也就是說length值已經被确立了。我們可以想象,這個length屬性一定被final修飾。

2.6 數組的優缺點

  • 優點
    • 數組在堆中是一塊連續的記憶體空間
    • 數組中存放的是同一類型的值
    • 我們要通路某個元素,是通過數組的下标進行通路,因為連續,元素的類型相同,因為每個元素的大小都是固定的,我們又能拿到首元素的位址,是以通路的速度會很快,效率很高
  • 缺點:
    • 數組中的元素存放在一段連續的記憶體空間上,而且數組一旦被建立,大小就固定了,不能改變。對于超出目前數組大小範圍的資料元素的存放,就需要另外開辟一個更大的數組空間,進行數組的拷貝。這樣增加系統的開銷。
    • 數組的删除和增加,都會造成大量的資料移動,效率不高。

2.7 數組的擴容

  • 數組的擴容,本質上沒有在原有的數組所在的堆記憶體空間上進行擴充,而是另外重新開辟了一塊記憶體空間。也就是說,原來的int[] a = 0x1234;擴容以後的int[] a 不再指向0x1234,而是指向了新開辟的數組的記憶體位址(0x2345)
  • 數組的擴容的步驟:

    第一步:開辟一個更大的數組

    第二步:将原數組中的内容拷貝過來

    第三步:将要存入的元素追加到更大數組中相應的位置

    第四步:将原數組的引用指向新數組的對象

2.8 為什麼推薦使用 “類型[] a”

  • 因為:類型[] 表示是一個數組類型,後邊的變量指的是這個數組的引用。
  • 如果是 “類型 辨別符[]”這種形式,會讓人誤解。也很難展現出引用資料類型的特征。
  • 是以,我們推薦使用 類型[] 數組名 的方式

2.9 二維數組

  • 二維數組的形式:
int[][] arr
           
  • 二維數組的定義
int[][] arr = {
    {1,2,3}, 
    {4,5,6}, 
    {7}
}; ----靜态的方式
    
int[][] arr = new int[3][5]; ----動态的方式
           

3 String類

public final class String //意味着:這是一個最終的類,沒有子類,不能被繼承
// All string literals in Java programs, 
// such as "abc", are implemented as instances of this class. 
// Strings are constant; their values cannot be changed after they are created
這句話什麼意思?
    字元串是常量,它們的值在它們被建立之後不能改變。
    String str = "abc";
	is equivalent to:等價于
	char data[] = {'a', 'b', 'c'};
	String str = new String(data);

分析:常量,什麼是常量?存放在哪裡?
    final static修飾的是常量
    存放在方法區記憶體中
    
    String的本質是什麼?也就是說String是怎麼實作的?
    char[] 數組。
    我們可以想到,char[]數組中的元素要不能被改變,則一定要被final修飾。
    
    String類型的資料全部存放于方法區的"字元串常量池"中。字元串一旦被建立,不能改變。
    String name = "abc";// 這意味着String是引用類型,name是引用類型的變量名
// 引用類型的變量隻能儲存位址,不能儲存實際的值。
// "abc"不是記憶體位址,它是一個實實在在的值。
// 是以"abc"指派給name,實際上是将"abc"存放的記憶體位址的值給到了name。
// 并不是将"abc"的本身給到了name。那麼,"abc"這個字元串一定是一個對象
// 這個對象存放在方法區記憶體中的字元串常量池中。
// 為什麼要怎麼做?要将字元串存放到方法區記憶體中的字元串常量池中?
// 為什麼要規劃這麼一塊記憶體空間?
// 對事物的描述,人類最能接受的方式是字元串。字元串是不是最利于識别的,也是用得最多的
// 使用率太高了,如果把它放在堆中,是不是很占空間。也很消耗JVM的性能。
// 把字元串做成常量的話,使用率是不是高一些。重複在堆中建立銷毀的次數是不是得到了緩解。
           
java進階第二講-數組、String類java進階第二講-數組、String類
java進階第二講-數組、String類java進階第二講-數組、String類
// 測試代碼
public class AarrayTest01 {

    public static void main(String[] args) throws Throwable {
        String str = "abc";
        str = "def";
        // 這是什麼意思?是兩個字元串對象被建立了,def的位址給到了str這個引用類型變量
        // 常量池中仍然存在"abc"
        // 字元串常量一旦建立就不能被改變

        System.out.println("abc".hashCode());
        System.out.println(str.hashCode());

        str += "d";
        // 這裡是合并了嗎?覆寫了原來的abc嗎?沒有,建立了一個新的

        System.out.println(str);
        String str1 = "abc";
        String string = "abc";
        System.out.println(str1 == string);
        System.out.println(string.hashCode());
        System.out.println("------------------");

        // 請問這裡建立了幾個字元串對象?3 存在于字元串常量池中的有幾個?3
        // "abc" "d" "abcd"
        // str = str + "d" ----> "abcd"
    }
}

    
           

ng = “abc”;

System.out.println(str1 == string);

System.out.println(string.hashCode());

System.out.println("------------------");

// 請問這裡建立了幾個字元串對象?3 存在于字元串常量池中的有幾個?3
    // "abc" "d" "abcd"
    // str = str + "d" ----> "abcd"
}
           

}