Java?面向?qū)ο笸ㄟ^new揭開對象實例化
更正說明:
我之前的的標(biāo)題有點文不對題,我這篇博客的內(nèi)容明明說的是:java中對象創(chuàng)建的過程,對內(nèi)存之種底層的東西,我其實提的不太多。
所以我原來的標(biāo)題:《當(dāng)你實例化對象時,在內(nèi)存中到底發(fā)生了什么》是不合適的
概念了解
想要知道內(nèi)存中發(fā)生了什么,我們先來了解兩個內(nèi)存概念????
- 堆內(nèi)存:保存對象的屬性內(nèi)容。堆內(nèi)存需要用new關(guān)鍵字來分配空間;
- 棧內(nèi)存:保存的是堆內(nèi)存的地址(在這里為了分析方便,可以簡單理解為棧內(nèi)存保存的是對象的名字)。
Student student1 = new Student()
這行代碼可以分為兩部分
1、Student student1 聲明對象,會在棧上開辟一塊區(qū)域,名叫student1,里面存了:堆中開辟的內(nèi)存的地址??
2、new Student() 實例化student1對象,在堆里開辟了一塊區(qū)域,名叫student1??
當(dāng)用等號將兩者關(guān)聯(lián)的時候,其實就是將棧上聲明的對象student1,指向堆上實例化的具體空間
如圖所示:

從圖中也可以看出,在“=”關(guān)聯(lián)的時候,就是將堆中student1開辟內(nèi)存的地址0X99存放到了棧里,可以吧內(nèi)存地址看成Student類的一把鑰匙??
實例化后對象student1獲得了這把鑰匙,所以可以在類中任意拿東西,即調(diào)用屬性、方法等??
(大多數(shù)情況下可以這么認(rèn)為,其實變量名student1儲存的不一定是地址??)
第一種情況
因此可以通過對象名 student1 ,給堆中的具體成員變量賦值、調(diào)用??。
其實棧中存放的就是堆中某一個內(nèi)存的引用,這就是對象引用的概念,其中的 student1 也被稱作對象的引用變量??
class Student {
String name; //學(xué)生類的屬性
int age;
public void eat() {
System.out.println(name + "在吃飯, 他" + age + "歲了"); // 學(xué)生類的行為(方法)
}
}
public class TestDemo3 {
// 不同的實例化對象在棧中擁有不同的空間,他們也指向堆中不同的內(nèi)存地址
public static void main(String[] args) {
Student student1 = new Student(); // 學(xué)生對象student1
student1.name = "小強"; // 通過 對象名.屬性 來給堆中的具體成員變量賦值
student1.age = 18;
student1.eat(); // 調(diào)用類中的eat()方法
Student student2 = new Student(); // 學(xué)生對象student2
student2.name = "小紅";
student2.age = 23;
student2.eat();
}
}
第二種情況
不同的實例化對象在棧中擁有不同的空間,他們也指向堆中不同的內(nèi)存地址,但是也可以有這樣的情況:棧中有不同的空間,他們指向堆中同一個內(nèi)存地址??。
class Dog {
String name;
int age;
public void show() {
System.out.println("姓名:" + name + " 年齡: " + age);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Dog one = new Dog();
Dog two = one;
}
}對象one在實例化后,擁有一塊棧的空間,空間里存放堆的一個內(nèi)存地址??
那么將one賦值給two之后,two的棧的空間里,也會存放one擁有的堆的內(nèi)存地址??。
用一個很形象的比喻,妻子帶著一幅畫嫁給了丈夫,那么她的畫也就屬于丈夫了,兩人共有??。
不論是丈夫還是妻子,只要是對畫做出了最后的更改,那么這幅畫的內(nèi)容就會改變。即最后一次修改是有效的,會覆蓋掉原先的內(nèi)容??
用代碼來展示:
class Dog {
String name;
int age;
public void show() {
System.out.println("姓名:" + name + " 年齡: " + age);
}
}
public class TestDemo4 {
public static void main(String[] args) {
Dog one = new Dog();
Dog two = one;
one.name = "阿黃";
one.age = 10;
two.name = "旺財";
two.age = 3;
one.show();
System.out.println("========這是分割線========");
two.show();
}
}
怎么樣!通過對象one對姓名和年齡的賦值是不是被覆蓋掉了,內(nèi)存中的場景大概是這樣

棧中的對象one、two同時指向堆中的同一塊空間,也就是不同的棧可以修改同一塊堆內(nèi)存的內(nèi)容??,這樣堆內(nèi)存的內(nèi)容自然就是最后對象two所賦值的內(nèi)容了??。
哈哈! 原來在我們實例化new一個對象的時候,內(nèi)存里偷偷干了這么多事啊??!
各位鐵汁們,我們下篇博客見,嘻嘻??
到此這篇關(guān)于Java 通過new揭開對象實例化的文章就介紹到這了,更多相關(guān)Java 對象實例化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringSecurity?認(rèn)證實現(xiàn)流程分析
SpringSecurity框架通過一個過濾器鏈來處理認(rèn)證和授權(quán),主要包括UsernamePasswordAuthenticationFilter負(fù)責(zé)處理登錄請求,本文給大家介紹SpringSecurity?認(rèn)證實現(xiàn)登錄校驗,感興趣的朋友跟隨小編一起看看吧2024-10-10
SpringBoot項目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法
最近做的這個項目中,用到了大量的枚舉類,下面這篇文章主要給大家介紹了關(guān)于SpringBoot項目中枚舉類型字段與前端和數(shù)據(jù)庫的交互方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
Spring + Spring Boot + MyBatis + MongoDB的整合教程
這篇文章主要給大家介紹了關(guān)于Spring + Spring Boot + MyBatis + MongoDB的整合教程,文中通過圖文以及示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。2017-12-12

