https://blog.csdn.net/qq_36934826/article/details/82685791java
問題引入這裏先定義一個很不標準的「書」類,這裏爲了方便演示就不對類的屬性進行封裝了。
class Book{ String name; //書名 double price; //價格 public void getInfo(){ System.out.println("name:"+name+";price:"+price); }}1問題引入這裏先定義一個很不標準的「書」類,這裏爲了方便演示就不對類的屬性進行封裝了。
class Book{ String name; //書名 double price; //價格 public void getInfo(){ System.out.println("name:"+name+";price:"+price); }}1234567在這個類中定義了兩個屬性和一個方法,固然也是能夠定義多和類和多個方法的。 類如今雖然已經定義好了,可是一個類要使用它必需要實例化對象,那麼對象的定義格式有一下兩種格式:
//聲明並實例化對象: 類名稱 對象名稱 = new 類名稱()Book book = new Book();123//分步完成聲明和實例操做: // |- 聲明對象: 類名稱 對象名稱 = null;Book book = null;// |- 實例化對象: 對象名稱 = new 類名稱();book = new Book();12345對象屬於引用數據類型,其和基本數據類型最大的不一樣在於引用數據類型須要進行內存分配,而關鍵字new主要的功能就是開闢內存空間,也就是說只要是使用引用數據類型就必須使用關鍵字new來開闢空間。有些時候咱們須要對對象屬性進行操做,那麼其中的堆棧內存空間又是如何分配的呢?接下來咱們來分析一下其中的過程。
堆內存與棧內存若是想對對象操做的過程進行內存分析,首先要了解兩塊內存空間的概念:
堆內存:保存每個對象的屬性內容,堆內存須要用關鍵字new才能開闢。棧內存:保存的是一塊堆內存的地址。堆內存很好理解,可能有人會有疑問爲何會有棧內存,舉個例子,比如學校有不少教室,每一個教室有一個門牌號,教室內放了不少的桌椅等等,這個編號就比如地址,老師叫小明去一個教室拿東西,老師必須把房間號告訴小明才能拿到,也就是爲何地址必須存放在一個地方,而這個地方在計算機中就是棧內存。
對象空屬性咱們先實例化一個對象,並對其的屬性不設置任何值
public class Test{ public static void main(String args[]){ Book book = new Book(); book.getInfo(); }}123456運行結果以下:
name:null;price:0.01其內存變化圖以下:
使用關鍵字new就在棧內存中開闢一個空間存放book對象,而且指向堆內存的一個空間,此時並未對其賦值,因此始終指向默認的堆內存空間。
操做對象屬性咱們先聲明並實例化Book類,並對實例出的book對象操做其屬性內容。
public class Test{ public static void main(String args[]){ Book book = new Book(); book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}12345678編譯執行後的結果以下:
name:深刻理解JVM;price:99.81內存變化圖以下:
分步實例化對象示例代碼以下:
public class Test{ public static void main(String args[]){ Book book = null; //聲明對象 book = new Book(); //實例化對象 book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}123456789很明顯結果確定和前面同樣
name:深刻理解JVM;price:99.81表面沒什麼區別,可是內存分配過程卻不同,接下來咱們來分析一下
任何狀況下只要使用了new就必定要開闢新的堆內存空間,一旦堆內存空間開闢了,裏面就必定會全部類中定義的屬性內容,此時全部的屬性內容都是其對應數據類型的默認值。
直觀的說就是棧內存先要指向一個null,而後等待開闢新的棧內存空間後才能指向其屬性內容。
NullPointerException的出現那麼若是使用了沒有實例化的對象,就會出現最多見也是最讓人頭疼的一個異常NullPointerException,像下面的代碼
public class Test{ public static void main(String args[]){ Book book = null;// book = new Book(); //實例化的這一步被註釋 book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}123456789在編譯的過程是不會出錯的,由於只有語法錯誤纔會在編譯時中斷,而這種邏輯性錯誤能成功編譯,可是執行的時候卻會拋出NullPointerException異常。 運行結果:
Exception in thread "main" java.lang.NullPointerException at language.Test.main(Test.java:19)1空指針異常是平時遇到最多的一類異常,只要是引用數據類型都有可能出現它。這種異常的出現也是很容易理解的,猶如你說今天被一隻恐龍追着跑,恐龍早就在幾個世紀前就滅絕了,現實生活中不可能存在,固然人們就會認爲你說的這句話是謊話。在程序中也同樣,沒有被實例化的對象直接調用其中的屬性或者方法,確定會報錯。
引用數據分析引用是整個java中的核心精髓,引用相似於C++中的指針概念,可是又比指針的概念更加簡單。 舉個簡單的例子,好比李華的小名叫小華,一天李華由於生病向老師請假了,老師問今天誰請假了,說李華請假了和小華請假了都是一個意思,小華是李華的別名,他們兩個都是對應一個個體。 若是代碼裏面聲明兩個對象,而且使用了關鍵字new爲兩個對象分別進行了對象的實例化操做,那麼必定是各自佔用各自的堆內存空間,而且不會互相影響。
例如:聲明兩個對象
public class Test{ public static void main(String args[]){ Book bookA = new Book(); Book bookB = new Book();
bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookA.getInfo();
bookB.name = "Java多線程"; bookB.price = 69.8; bookB.getInfo(); }}1234567891011121314運行結果以下:
name:深刻理解JVM;price:99.8name:Java多線程;price:69.812咱們來分析一下內存的變化
接下來咱們看看那對象引用傳遞
例如:對象引用傳遞
public class Test{ public static void main(String args[]){ Book bookA = new Book(); //聲明並實例化對象 Book bookB = null; //聲明對象 bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookB = bookA; //引用傳遞 bookB.price = 69.8; bookA.getInfo(); }}1234567891011運行結果以下:
name:深刻理解JVM;price:69.81嚴格來說bookA和bookB裏面保存的是對象的地址信息,因此以上的引用過程就屬於將bookA的地址賦給了bookB,此時兩個對象指向的是同一塊堆內存空間,所以任何一個對象修改了堆內存以後都會影響其餘對象。
一塊堆內存能夠同時被多個棧內存所指向,可是反過來,一塊棧內存只能保存一塊堆內存空間的地址。
垃圾的產生先看以下代碼:
public class Test{ public static void main(String args[]){ Book bookA = new Book(); //聲明並實例化對象 Book bookB = new Book(); //聲明並實例化對象 bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookB.name = "Java多線程"; bookB.price = 69.8; bookB = bookA; //引用關係 bookB.price = 120.8; bookA.getInfo(); }}12345678910111213運行結果以下:
name:深刻理解JVM;price:120.81整個過程內存又發生了什麼變化呢?咱們來看一下
在此過程當中原來bookB所指向的堆內存無棧內存指向,一塊沒有任何棧內存指向的堆內存空間就將成爲垃圾,等待被java中的回收機制回收,回收以後會釋放掉其佔用的空間。
雖然在java中支持了自動的垃圾收集處理,可是在代碼的編寫過程當中應該儘可能減小垃圾空間的產生。
歡迎來個人博客網站逛一逛~blog.beifengtz.com--------------------- 做者:beifengtz 來源:CSDN 原文:https://blog.csdn.net/qq_36934826/article/details/82685791 版權聲明:本文爲博主原創文章,轉載請附上博文連接!234567在這個類中定義了兩個屬性和一個方法,固然也是能夠定義多和類和多個方法的。 類如今雖然已經定義好了,可是一個類要使用它必需要實例化對象,那麼對象的定義格式有一下兩種格式:
//聲明並實例化對象: 類名稱 對象名稱 = new 類名稱()Book book = new Book();123//分步完成聲明和實例操做: // |- 聲明對象: 類名稱 對象名稱 = null;Book book = null;// |- 實例化對象: 對象名稱 = new 類名稱();book = new Book();12345對象屬於引用數據類型,其和基本數據類型最大的不一樣在於引用數據類型須要進行內存分配,而關鍵字new主要的功能就是開闢內存空間,也就是說只要是使用引用數據類型就必須使用關鍵字new來開闢空間。有些時候咱們須要對對象屬性進行操做,那麼其中的堆棧內存空間又是如何分配的呢?接下來咱們來分析一下其中的過程。
堆內存與棧內存若是想對對象操做的過程進行內存分析,首先要了解兩塊內存空間的概念:
堆內存:保存每個對象的屬性內容,堆內存須要用關鍵字new才能開闢。棧內存:保存的是一塊堆內存的地址。堆內存很好理解,可能有人會有疑問爲何會有棧內存,舉個例子,比如學校有不少教室,每一個教室有一個門牌號,教室內放了不少的桌椅等等,這個編號就比如地址,老師叫小明去一個教室拿東西,老師必須把房間號告訴小明才能拿到,也就是爲何地址必須存放在一個地方,而這個地方在計算機中就是棧內存。
對象空屬性咱們先實例化一個對象,並對其的屬性不設置任何值
public class Test{ public static void main(String args[]){ Book book = new Book(); book.getInfo(); }}123456運行結果以下:
name:null;price:0.01其內存變化圖以下:
使用關鍵字new就在棧內存中開闢一個空間存放book對象,而且指向堆內存的一個空間,此時並未對其賦值,因此始終指向默認的堆內存空間。
操做對象屬性咱們先聲明並實例化Book類,並對實例出的book對象操做其屬性內容。
public class Test{ public static void main(String args[]){ Book book = new Book(); book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}12345678編譯執行後的結果以下:
name:深刻理解JVM;price:99.81內存變化圖以下:
分步實例化對象示例代碼以下:
public class Test{ public static void main(String args[]){ Book book = null; //聲明對象 book = new Book(); //實例化對象 book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}123456789很明顯結果確定和前面同樣
name:深刻理解JVM;price:99.81表面沒什麼區別,可是內存分配過程卻不同,接下來咱們來分析一下
任何狀況下只要使用了new就必定要開闢新的堆內存空間,一旦堆內存空間開闢了,裏面就必定會全部類中定義的屬性內容,此時全部的屬性內容都是其對應數據類型的默認值。
直觀的說就是棧內存先要指向一個null,而後等待開闢新的棧內存空間後才能指向其屬性內容。
NullPointerException的出現那麼若是使用了沒有實例化的對象,就會出現最多見也是最讓人頭疼的一個異常NullPointerException,像下面的代碼
public class Test{ public static void main(String args[]){ Book book = null;// book = new Book(); //實例化的這一步被註釋 book.name = "深刻理解JVM"; book.price = 99.8; book.getInfo(); }}123456789在編譯的過程是不會出錯的,由於只有語法錯誤纔會在編譯時中斷,而這種邏輯性錯誤能成功編譯,可是執行的時候卻會拋出NullPointerException異常。 運行結果:
Exception in thread "main" java.lang.NullPointerException at language.Test.main(Test.java:19)1空指針異常是平時遇到最多的一類異常,只要是引用數據類型都有可能出現它。這種異常的出現也是很容易理解的,猶如你說今天被一隻恐龍追着跑,恐龍早就在幾個世紀前就滅絕了,現實生活中不可能存在,固然人們就會認爲你說的這句話是謊話。在程序中也同樣,沒有被實例化的對象直接調用其中的屬性或者方法,確定會報錯。
引用數據分析引用是整個java中的核心精髓,引用相似於C++中的指針概念,可是又比指針的概念更加簡單。 舉個簡單的例子,好比李華的小名叫小華,一天李華由於生病向老師請假了,老師問今天誰請假了,說李華請假了和小華請假了都是一個意思,小華是李華的別名,他們兩個都是對應一個個體。 若是代碼裏面聲明兩個對象,而且使用了關鍵字new爲兩個對象分別進行了對象的實例化操做,那麼必定是各自佔用各自的堆內存空間,而且不會互相影響。
例如:聲明兩個對象
public class Test{ public static void main(String args[]){ Book bookA = new Book(); Book bookB = new Book();
bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookA.getInfo();
bookB.name = "Java多線程"; bookB.price = 69.8; bookB.getInfo(); }}1234567891011121314運行結果以下:
name:深刻理解JVM;price:99.8name:Java多線程;price:69.812咱們來分析一下內存的變化
接下來咱們看看那對象引用傳遞
例如:對象引用傳遞
public class Test{ public static void main(String args[]){ Book bookA = new Book(); //聲明並實例化對象 Book bookB = null; //聲明對象 bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookB = bookA; //引用傳遞 bookB.price = 69.8; bookA.getInfo(); }}1234567891011運行結果以下:
name:深刻理解JVM;price:69.81嚴格來說bookA和bookB裏面保存的是對象的地址信息,因此以上的引用過程就屬於將bookA的地址賦給了bookB,此時兩個對象指向的是同一塊堆內存空間,所以任何一個對象修改了堆內存以後都會影響其餘對象。
一塊堆內存能夠同時被多個棧內存所指向,可是反過來,一塊棧內存只能保存一塊堆內存空間的地址。
垃圾的產生先看以下代碼:
public class Test{ public static void main(String args[]){ Book bookA = new Book(); //聲明並實例化對象 Book bookB = new Book(); //聲明並實例化對象 bookA.name = "深刻理解JVM"; bookA.price = 99.8; bookB.name = "Java多線程"; bookB.price = 69.8; bookB = bookA; //引用關係 bookB.price = 120.8; bookA.getInfo(); }}12345678910111213運行結果以下:
name:深刻理解JVM;price:120.81整個過程內存又發生了什麼變化呢?咱們來看一下
在此過程當中原來bookB所指向的堆內存無棧內存指向,一塊沒有任何棧內存指向的堆內存空間就將成爲垃圾,等待被java中的回收機制回收,回收以後會釋放掉其佔用的空間。
雖然在java中支持了自動的垃圾收集處理,可是在代碼的編寫過程當中應該儘可能減小垃圾空間的產生。--------------------- 做者:beifengtz 來源:CSDN 原文:https://blog.csdn.net/qq_36934826/article/details/82685791 版權聲明:本文爲博主原創文章,轉載請附上博文連接!多線程