[Java基礎]由數組到內存地址的使用及理解


一.數組的概念

  1.數組是Java里自帶的引用數據類型,是一個同一種數據類型的集合,數組的構成有四大要素:數組的數據類型,數組的長度,數組的數組名,數組的下標:語法如

int[] a;
a = new int[10]; String[] s = {"aaa","bbb","ccc"}; Student[] stu = new Student[10];

     i.數組的數據類型決定了這個數組內能放數組的類型,一個數組不能存放有不同的數組類型的數據

     ii.數組長度一旦定義下來了便無法更改

     iii.數組的名字是指向該數組內存地址的

     iv.數組的下標是從0開始的

  2.關於數組的補充和些許算法

    i.遍歷數組,for()循環,從0下標到數組.length-1下標一個一個找就好了,或者使用Stream.of()把它變成一個流,或者用別的方法如forEach()遍歷

    ii.數組的排序:

int a[] = {1,5,3,9,4,5};
//冒泡排序
for(int i =0;i < a.length-1;i++){
     for(int j =0;j <a.length-i-1;j++){
          if(a[j] > a[j+1]){
            int temp = a[j];
            a[j] = a[j+1];
            a[j+1] = temp;
        }                           
    }      
}    
//選擇排序
for(int i = 0; i < a.length-1;i++){
    for(int j = i+1; j < a.length;j++){
        if(a[i] > a[j]{
            int temp = a[j];
            a[j] = a[i];
            a[i] = temp;
        }
    }
}

二.內存地址的基礎理解

  1.在數組里,對內存的理解:

    i.當代碼運行至初始化一個數組如int[] a = new int[5];此時內存便會在堆內存里開辟一個能存放長度為5的整數數組的空間,而對數組名,jvm會在棧內存中開辟一個空間存放該數組名,而空間里的值則是一個指向堆內數組空間的內存地                   址

  2.如上所說,jvm里有一個棧的內存空間,一個堆的內存空間,那么這兩個空間jvm到底會如何使用呢?

    i.棧內存,也就是方法棧,每當jvm編譯運行一個方法時便會開辟一個方法棧幀,用來存放局部變量表,操作數棧,動態鏈接,方法出口等信息,顯而易見該內存的存放數據的結構為棧,先進后出,這也是為什么局部變量會覆蓋全局變量的原因,而在這個方法棧幀中,jvm每讀取一個基礎數據類型的變量名,都會把他存放在一個棧內,而里面存放的都是基礎數據類型變量,引用對象變量名,方法出口等信息

    ii.堆內存,這個內存是jvm管理的最大的內存空間,里面存放了引用數據類型的數據,如各種類的實例,各種數組,各種接口

    iii.棧內的引用對象變量名是怎么指向堆內存的實例的呢,那是因為棧內的每個引用對象變量名里存放的數據都是指向相應實例的內存地址

  3.==和.equals()的區別

    i.在Object類內其實.equals()和==沒區別,代碼如下:

 public boolean equals(Object obj){
    return (this == obj);
}

     所以說都是判斷兩方在棧內存中存放的數據

    ii.那為什么說引用數據類型要用.equals()呢,如String之類

      

String a = new String ("aaa");
String b = new String ("aaa");
System.out.println(a == b);   //輸出的是false
System.out.println(a.equals(b)); //輸出的是true
/*
  那為什么會出現這種情況呢?不是說都是比較棧內存中存放的數據嗎?
  那要回到上方的棧與堆內儲存數據的情況解析了,明顯棧內存放的兩個引用變量 a,b 指向的是不同的引用對象實例
  而如果要比較他們的值 == 顯然不能排上用場,因為存放的是不同的內存地址,== 返回的肯定是false,那為了解決這一情況java在常用類內如String 重寫了.equals()這一方法
  使得其return的不是 this == obj 而是 this.value == obj.value
  所以如果使用這種引用類型數據的時候請使用.equals()
  我們下面再看另一種情況
*/
String c = "abc";
String d = "abc";
System.out.println( c == d); //這次輸出的是true
/*
  那這次又是因為什么呢?
  這要講一下jvm內的常量池空間,當給String 類型直接賦值一個字符串 如"abc"這種,jvm就會自動在常量池內放一個值為"abc"的字符串並把它認為是一個常量
  而一個常量池內最多只能有一個相同的字符串常量,那后來給d賦值"abc"時,jvm自動把d的內存地址指向了這個字符串常量
  因此這個時候 c d 兩個引用變量內存放的內存地址都是指向這個字符串常量的,因此這個時候使用 == 兩個相同的內存地址比較 返回的boolean值必然是 true
*/


 

  4.對於方法內參數的傳遞

    i.當jvm在一個方法棧幀內讀取到了另一個方法的出現,就會開辟另一個方法棧幀存放里面的新的數據,如局部變量表之類

    ii.新的方法幀棧存放的數據由原方法幀棧傳遞而來所以就會出現下方的情況:

public static void main(String[] args){
  int a = 0;
  String s = "a";
  int[] array = {1,5,3,6};
}
public static void function(int a){ }
public static void function(String s){
}
public static void function(int[] array){
}
/*
  顯然這三個方法傳遞的值都不同,一個是基礎數據類型,一個是String引用數據類型,一個是數據引用數據類型
  由原方法棧幀到新方法棧幀內的數據轉移情況因參數傳遞的都是一個變量表內的值,但因為這兩種數據類型變量在表內存放的數據不同而產生了兩個不同的結果
  1.基礎數據類型
    新方法棧幀接受到了一個基礎數據類型的變量的值后會在自己的棧空間內新開辟一個與之相同的空間存放這個值,所以這個空間內無論這個值怎么變都不會影響到原方法棧幀內那個棧空間內的值
  2.引用數據類型
    新方法棧幀接收到了這個變量的值后也會做與接受基礎數據類型相同的操作,但因為這種變量存放的數據是指向一個對象實例的地址,所以新棧內的對這個數據的操作都會映射到那個儲存在堆內的對象實例,所以這里的操作會影響到實例數據的變化
*/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM