Java創(chuàng)建對象之顯示創(chuàng)建與隱式創(chuàng)建
一. 對象簡介
1. 概念
在之前的文章中,其實已經給大家解釋過對象的概念了。在面向對象的編程規(guī)范中,“一切皆對象”,對象就是面向對象編程的核心?,F實世界中的每一個物體都是對象!當然,這個“對象”不是你懷里撒嬌的男/女朋友,而是指某個“類”的一個實例。
比如,“人”是一個“整體”的概念,它不是“個體”的概念,所以“人”是“類別(模板)”,而不是對象。但是在人這個“類別”中,有法外狂徒張三這個個體,張三就是一個具體的“對象”。每個對象都有自己的狀態(tài)和行為,比如張三的狀態(tài)有:身高、體重、愛好;行為有:吃、喝、piao、du、抽,坑、蒙、拐、騙、偷等。
2. 行為和特征
一個對象主要包括行為和特征(狀態(tài)、屬性)兩個核心要素。

行為:一般是動詞,指的是方法,代表一個對象能干什么,具有哪些功能或能力,例如人可以吃飯、睡覺、說話、工作等;在Java中,一般是用方法來表明對象所具有的行為。
特征:也可以叫做狀態(tài),一般是名詞,指的是屬性,代表一個對象有什么特點或參數,例如每個人的姓名、年齡、性別、體重等。在Java中,一般是用變量來表明對象的狀態(tài)。
3. 對象的創(chuàng)建方式(重點)
對象就是類的實例化,也就是根據類來創(chuàng)建一個具體的對象,就好比我們使用一個手機殼模具制造出一個具體的手機殼。接下來就給大家講一下,在Java中創(chuàng)建對象的兩種主要方式:顯式創(chuàng)建與隱式創(chuàng)建。
3.1 顯式創(chuàng)建
其中顯式創(chuàng)建對象時,又有以下4種具體的創(chuàng)建方式:
- 使用new關鍵字創(chuàng)建對象;
- 使用newlnstance()實例方法創(chuàng)建對象;
- 使用clone()方法創(chuàng)建對象;
- 使用ObjectlnputStream對象的readObject()方法創(chuàng)建對象。
3.2 隱式創(chuàng)建
隱式創(chuàng)建對象主要是包括以下幾種方式:
- 給String字符串變量賦值;
- “+”號拼接多個字符串;
- JVM虛擬機加載類時隱式創(chuàng)建類對象。
接下來分別給大家講解一下這幾種創(chuàng)建對象的方式。受限于篇幅,今天主要是給大家講解通過new關鍵字創(chuàng)建對象的方式,其他的方式我們以后再細講。
二. 顯式創(chuàng)建
1. 使用new關鍵字創(chuàng)建對象
1.1 new簡介
我們知道,new是"新的"的意思。在Java中,new是一個關鍵字,它用于創(chuàng)建一個新的類實例,即新的類對象。所以在Java中,創(chuàng)建新對象也可以叫做實例化對象。 對于引用類型來說,如果該類型沒有進行實例化,也就是沒有進行對象的創(chuàng)建,那么該對象的屬性、方法等在內存中都是不存在的。只有使用new關鍵字創(chuàng)建了對象之后,這個對象在內存中才會存在,才能使用。
1.2 new作用
當一個引用類型的變量被聲明以后,如果沒有進行初始化,那么它就不指向任何對象,我們也就沒辦法使用該變量。所以我們就可以通過new關鍵字對該變量進行初始化,具體地來說,new關鍵字的作用如下:
- 為新對象及對象中的各實例變量分配內存空間;
- 將新對象中的各實例變量自動初始化成對應類型的默認值;
- 初始化對象,并給各實例變量賦予正確的初始值;
- 調用引用類型對應的構造方法;
- 返回對象的引用。
1.3 基本語法
new關鍵字創(chuàng)建對象的語法格式如下:
類名 對象名 = new 類名();
1.4 代碼案例
為了讓大家更好地理解new的用法,給大家設計了如下代碼案例。
/**
* @author
*/
public class Demo01 {
public static void main(String[] args) {
// new關鍵字
Person p1 = new Person();
}
}
在這段簡單的代碼中,Person p1=new Person();,前半部分Person p1,表示是在內存中分配一個Person類型的變量p1。后半部分new Person();,表示利用new關鍵字和構造方法來創(chuàng)建一個Person類型的對象,Person()是構造方法的名字。當構造方法執(zhí)行完,這個Person類型的對象就建造出來了,也就為其分配了對應的內存。
雖然p1是引用類型的變量,但p1自身會存儲在棧內存中。而使用new關鍵字創(chuàng)造出來的對象,則被存儲在堆內存(heap)中。且在new關鍵字真正創(chuàng)建出引用類型的對象之后,會把這個對象在內存中的地址返回給p1變量進行引用,這樣我們就可以通過調用p1找到對內存中的Person對象。
所以Person p1=new Person();這行代碼的作用就是,把Person對象在內存中的地址 賦值 給變量p1。在Java中,我們可以把p1變量叫做引用變量,或者簡稱為引用。又因為p1變量中存放的是引用類型的內存地址值,我們也可以把p1的值叫做引用地址。
2. newlnstance()方法
除了使用new關鍵字創(chuàng)建對象之外,我們還可以使用newInstance()方法創(chuàng)建對象。該方法是java.lang.Class 或 java.lang.reflect.Constuctor類中的實例方法,其語法格式如下:
java.lang.Class 類對象名稱 = java.lang.Class.forName(要實例化的類全稱);
類名 對象名 = (類名)Class類對象名稱.newInstance();
我們在調用java.lang.Class類中的forName()方法時,需要將待實例化類的全限定名(如 com.yyg.Person)作為參數傳遞進來,然后再調用 java.lang.Class類對象的newInstance()方法創(chuàng)建對象。
/**
* @author
*/
public class Demo01 {
public static void main(String[] args) {
//newInstance()方法創(chuàng)建對象
try {
Class<?> clazz = Class.forName("com.yyg.Person");
Person p2 = (Person) clazz.newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
因為這一塊的內容涉及到了反射的知識點,后面會專門講解反射,這一塊的內容大家先有所了解即可。
3. clone()方法
第三種顯式創(chuàng)建對象的方法,就是利用實例對象的clone()方法進行對象的復制,也可以創(chuàng)建一個新對象出來。clone()方法創(chuàng)建對象時,不會調用類的構造方法,它會創(chuàng)建一個復制的對象,這個對象和原來的對象具有不同的內存地址,但它們的屬性值卻相同。
另外clone()方法是Java Object對象中被protected修飾的方法,可供子類調用以實現子類的克隆邏輯,但不能直接調用。并且我們使用該方法創(chuàng)建對象時,還要求待實例化的類必須實現 java.lang.Cloneable接口,否則會拋出 java.lang.CloneNotSupportedException異常,比較麻煩,所以該方法并不常用。 clone()方法創(chuàng)建對象的語法格式如下:
類名 對象名 = (類名)已創(chuàng)建好的類對象名.clone();
4. readObject()方法
我們還可以使用java.io.ObjectlnputStream對象的readObject()方法來創(chuàng)建一個新對象。ObjectlnputStream是IO流中的內容,以后會詳細講解Java中的IO流,大家對此先有一個大致的印象即可。
5. 小結
在上面給大家提到了4種顯式創(chuàng)建對象的方式,在此我們進行一個小小的總結:
- new關鍵字是最常用的創(chuàng)建對象方式;
- 使用 new關鍵字 或 Class對象的newInstance()方法 創(chuàng)建對象時,都會調用類的構造方法;
- 使用 Class類的newInstance()方法 創(chuàng)建對象時,會調用類的默認構造方法,即無參構造方法;
- 使用 Object類的clone()方法 創(chuàng)建對象時,不會調用此類的構造方法,只會創(chuàng)建一個復制出的對象,該對象和原來的對象具有不同的內存地址,但它們的屬性值相同;
- 如果類沒有實現Cloneable接口卻調用它的clone()方法,會拋出 java.lang.CloneNotSupportedException異常。
三. 隱式創(chuàng)建
在Java中,除了可以顯式地創(chuàng)建對象之外,還可以隱式地創(chuàng)建對象。隱式創(chuàng)建對象主要是通過以下幾種方式:
- 給String字符串變量賦值;
- “+”號拼接多個字符串;
- JVM虛擬機加載類時隱式創(chuàng)建類對象。
1. 給String字符串變量賦值
我們經常給一個字符串變量賦值,如下所示:
String str = "Hello,壹哥";
上面的str變量,其實就是一個String對象,該對象會由JVM虛擬機隱式地創(chuàng)建出來。
2. “+”號拼接多個字符串
我們知道,“+”運算符有兩個基本作用:加法運算和字符串拼接。當進行字符串拼接時,其運算的結果是一個新的 String對象,示例如下:
String str1 = "Hello"; String str2 = "一一哥"; String str3 = str1+str2; // str3引用一個新的String對象
通過上面的語句,JVM會隱式地創(chuàng)建出第3個String對象。
3. JVM虛擬機加載類時隱式創(chuàng)建類對象
當Java的JVM虛擬機加載一個類時,會隱式地創(chuàng)建出一個可以描述這個類的Class實例對象。類的加載是指把類的.class字節(jié)碼文件讀到內存中,把它存放到運行時數據區(qū)的方法區(qū)中,然后會在堆區(qū)創(chuàng)建一個 java.lang.Class對象,用來封裝類在方法區(qū)內的數據結構。
4. 小結
無論我們是釆用顯式或是隱式方式創(chuàng)建對象,Java虛擬機都會在創(chuàng)建對象時包含以下步驟:
- 給對象分配內存;
- 將對象的實例變量自動初始化成該變量類型的默認值;
- 初始化對象,給實例變量賦予正確的初始值。
四. 對象的使用
1. 簡介
我們在通過一系列方式創(chuàng)建好對象之后,那么這個對象該怎么用呢?我們知道對象中有狀態(tài)和行為兩個核心要素,那怎么來調用一個對象的行為和狀態(tài)呢?Java中,一個普通的實例對象調用它的行為和狀態(tài),基本的語法格式如下:
//調用狀態(tài)
對象.屬性名;
//調用方法
對象.方法名();
接下來我們通過一個小案例給大家展示一下。
2. 使用
/**
* @author
*/
public class Demo02 {
public static void main(String[] args) {
// 對象的使用
//先創(chuàng)建一個對象
Person p1=new Person();
//調用對象的屬性(該屬性不能是私有的,否則別的類中無法看到)--狀態(tài).
String name = p1.name;
//調用對象的方法
p1.eat();
p1.speak("一一哥", "男", 18);
}
}
大家要注意,當我們在A類中調用B類對象時,B類對象的屬性或方法不能是私有的,否則在A類中會無法看到該屬性或方法。
五. 創(chuàng)建對象的內存分析(重點)
1. 內存簡介
Java程序在運行時,操作系統(tǒng)會給程序分配三塊主要的內存空間:棧內存、堆內存、方法區(qū)。
- 棧內存: 棧內存也叫做虛擬機棧,可以存放基本類型的數據和引用類型的地址,主要是局部變量。 這些 局部變量存放了編譯期可知長度的各種基本數據類型和對象引用,方法執(zhí)行完就會自動釋放。棧內存具有先進后出、占用空間比較小、存取速度相對較快的特點。
- 堆內存: 堆內存中可以存放各對象實例(所有new出來的對象都是)和數組都在堆中存放,即堆中存放的是引用類型的實際數據。 堆內存占用的空間比較大,存取速度相對較慢。
- 方法區(qū): 方法區(qū)主要用于存儲類信息、常量、靜態(tài)變量,靜態(tài)代碼塊、即時編譯器(JIT Compiler)編譯后的代碼數據等 , 簡單言之就是存儲類的結構信息。類的結構信息包括類的名稱、方法信息、字段信息等。在方法區(qū)中,有一塊空間叫做常量池(串池),用來存放字符串常量。還有一塊空間叫做靜態(tài)區(qū),用來存儲靜態(tài)變量等靜態(tài)數據。但在JDK 7之后,常量池、靜態(tài)區(qū)作為堆中的一個子部分,方法區(qū)的概念被弱化。
2. 內存分析
/**
* @author
*/
public class Demo02 {
public static void main(String[] args) {
// 對象的使用
//先創(chuàng)建一個Person對象
Person p1=new Person();
p1.name="一一哥";
p1.age=18;
p1.sex="男";
//創(chuàng)建p2對象
Person p2=new Person();
}
}
在上述代碼中,我們定義的Person類型p1變量實際上是一個引用,它會被存放在棧內存中,而存放實際數據的Person對象則存放在堆內存中。如下圖所示:

根據上面的內存分析圖可知:
- Person類中包含了name、age、sex三個屬性,它們分別是String、int、String類型。我們知道,它們的默認值分別是null、0、null。
- 我們創(chuàng)建一個p1對象之后,p1會被存放在棧區(qū),然后p1會通過堆中Person對象的內存地址,去找到該對象被實例化的內容(即name、age、sex等)。
- Java代碼中剛創(chuàng)建出來的對象屬性都是采用默認值(null、0、null),等我們通過"對象.屬性"的方式對屬性進行重新賦值后,堆內存中存儲的才是賦值后的內容。
- 我們創(chuàng)建的另一個對象p2,p2依然在棧區(qū),但并沒有對p2進行初始化,所以p2的屬性在堆內存中都是默認值。
- 堆內存中的每一個對象,都有一個獨立的內存空間。
六. 結語
至此,就給大家把Java的對象介紹完畢了,現在你知道幾種創(chuàng)建對象的方式呢?最后再跟大家說一下,不管我們用哪種方式創(chuàng)建出來的對象,每個對象都是相互獨立的。這些不同的對象在內存中會占有獨立的內存地址,且每個對象都具有自己的生命周期。當一個對象的生命周期結束時,對象就變成了垃圾,這些垃圾對象會被JVM虛擬機自帶的GC垃圾回收機制來處理。
以上就是Java創(chuàng)建對象之顯示創(chuàng)建與隱式創(chuàng)建的詳細內容,更多關于Java創(chuàng)建對象的資料請關注腳本之家其它相關文章!
相關文章
自帶IDEA插件的阿里開源診斷神器Arthas線上項目BUG調試
這篇文章主要為大家介紹了自帶IDEA插件阿里開源診斷神器Arthas線上項目BUG調試,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
淺談@FeignClient中name和value屬性的區(qū)別
這篇文章主要介紹了@FeignClient中name和value屬性的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07

