「將某 class 產生出一個 instance 之後,此 class 所有的 instance field 都會新增一份,那麼所有的 instance method 是否也會新增一份?」我常常看到網路上有人在討論此問題,所以寫了這篇文章,以為解釋。
Member 的種類
類別(class)的內部組成統稱為成員(member),如果依據成員是「資料」還是「程式」來區分,可以分成:
* 資料,被稱為 field
* 程式,被稱為 method
如果再依據有無使用 static 修飾而細分,則成員可細分成四種:
* class field:有用 static 修飾的 field
* class method:有用 static 修飾的 method
* instance field:沒有用 static 修飾的 field
* instance method:沒有用 static 修飾的 method
顧名思義,class field/method 和 class 本身有密切的關係,而 instance field/method 則與 instance(也就是物件)有密切的關係。請看下面的範例程式。
public class Class1 {
public static int classField;
public static void classMethod1() {
// ...
}
public static void classMethod2() {
// ...
}
public int instanceField;
public void instanceMethod1() {
// ...
}
public void instanceMethod2() {
// ...
}
}
public class Class2 {
public static void classMethod () {
// ...
}
public void instanceMethod() {
// ...
}
}
Field
宣告 field 時,如果前面加上 static 的修飾字,就會使得此 field 變成是 class field。一個 class field 永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入(load)記憶體之後就立刻配置的(allocate),感覺就如同此 field 與該 class 本身相關,而不是與該 class 的 instance 相關。class field 可以被同一個 class 的 class method 內部所直接使用,舉例來說,上述的 classMethod1() 內部可以出現 classField。如果 Class1 的 class method 或 instance method 欲使用到 Class2 的 class field,就必須在前面冠上 Class2,例如:Class2.classField。
宣告field時,如果前面「不」加上 static 的修飾字,就會使得此 field 變成是 instance field。對 instance field 而言,每產生一個instance(物件)就多一塊 instance field 的記憶體,每少一個 instance 就少一塊 instance field 的記憶體。instance field 可以被同一個 instanc e的 instance method 內部所直接使用,舉例來說,上述的 instanceMethod1() 內部可以出現 instanceField。如果某 class 的class method 或 instance method 欲使用到某 instance 的 instance field,就必須在前面冠上 instance 名稱,例如:obj.classField。
Method
宣告 method 時,如果前面加上 static 的修飾字,就會使得此 method 變成是 class method。對 class method 而言,永遠只佔用一塊記憶體,而且此記憶體空間是在此 class 一被載入進記憶體之後就立刻配置的,就如同此 method 是與該 class 本身相關,而不是與該 class 的 instance 相關。class method 可以被同一個 class 的任何 class method 內部所直接使用,舉例來說,上述的classMethod1() 內部可以出現 classMethod2()。如果 Class1 的 class method 或 instance method 欲使用到 Class2 的 classMethod(),就必須在前面冠上 Class2,也就是 Class2.classMethod()。
宣告 method 時,如果前面「不」加上 static 的修飾字,就會使得此 method 變成是 instance method。對 instance method 而言,每產生一個 instance「並不會」多一塊 instance method 的記憶體。同一個 method 不管被調用(invoke)幾次,也不管被調用時的instance 是何者,每次的程式碼完全都一樣,差別只在每次執行時資料不同,而資料是存放在 call stack 中,所以不會混淆。在 instance method 內,資料的來源包括了參數和 instance field。參數被傳進來變成 call stack 內的 entry,所以不會混淆,這很容易理解,但是 instance field 是如何區隔開來的(前面剛提過:instance field 會隨著 instance 數目增加而增加),這是透過隱匿(implicit)的 this 參數來達到了,稍後會有說明。instance method 可以被同一個 instance 的 instance method 內部所直接使用,舉例來說,上述的 instanceMethod1() 內部可以出現 instanceMethod2()。如果某 class 的 class method 或 instance method 欲使用到某 instance 的某 instance method,就必須在前面冠上此 instance 名稱,例如:obj.classMethod()。
隱匿的 this 參數
綜合上面的敘述來看:
* class field:共用一塊記憶體
* class method:共用一塊記憶體
* instance field:隨著每個 instance 各有一塊記憶體
* instance method:共用一塊記憶體
instance method 為什麼不是隨著每個 instance 佔有一塊記憶體,反倒是共用一塊記憶體?其實,讓每個 instance method 如同instance field 一樣,隨著每個 instance 佔有一塊記憶體,這麼做當然是可以的,只是 Java 編譯器和 JVM 都不這麼做,因為太浪費記憶體空間了。一個 field 少則佔用一個 byte,多則佔用數百 Byte,但是 method 少則數個 byte,多則數百 Kilo Byte。Mehtod耗費的記憶體是 field 的數百倍,甚至數千倍,當然是能共用就盡量共用,比較不會消耗記憶體。既然 JVM 讓一個 class 的所有instance 共用相同的 instance method,下面兩行程式碼在 instanceMethod() 內部時,如何區分是 instance1 或 instance2?
instance1.instanceMethod();
instance2.instanceMethod();
因為編譯器會幫我們在把 instance1 和 instance2 個別傳入 instanceMethod() 中當作第一個參數。也就是說,任何 instance method 參數的實際個數都會比表面上多一個,這個多出來的參數是由 Java 編譯器幫我們加上去的,用來代表對應的 instance。此參數的變數名稱為 this,也是 Java 的一個關鍵字(keyword)。
當調用某個 instance method 或使用某個 instance field 時,你必須在前面加上該 instance 的名稱,如果該 instance method/field 相關的 instance 和當時程式碼所在的 instance method 的 instance 指的是同一個 instance 時,該 instance 的名稱就是 this,這種情況下,你也可以選擇不在前面加上「this.」。
然而,在某些狀況下,非得在前面加上「this.」不可。例如,當method中的參數或區域變數和 instance field 名稱完全相同時,如果不在前面冠上「this.」,那麼指的是參數或區域變數;如果在前面冠上「this.」,那麼指的才是 instance field。
分享到:
相关推荐
ZZ-B-225B.027815.zip
### K2980ZZ-TR-E-VB N-Channel沟道SOT23 MOSFET晶体管参数介绍与应用说明 #### 概述 K2980ZZ-TR-E-VB是一款高性能N-Channel沟道MOSFET(金属氧化物半导体场效应晶体管),采用SOT23封装形式。这款MOSFET具有低导...
根据给定的信息,本文将详细解析“2SK2980ZZ-TR-E-VB”这款SOT23封装N-Channel场效应MOS管的关键技术特性与应用领域。 ### 一、产品概述 2SK2980ZZ-TR-E-VB是一款采用SOT23封装的N-Channel沟道MOSFET(金属氧化物...
《ZZ Fibo Trader - MetaTrader 5 EA 深度解析》 ZZ Fibo Trader 是一款专为 MetaTrader 5(MT5)平台设计的自动交易专家顾问(EA),其核心在于结合了斐波那契回调线分析和抛物线止损系统,为交易者提供了智能化的...
ZZ-2021030 网络搭建与应用赛项赛卷《网络环境》.pdf
《DT_ZZ_optimized - MetaTrader 4脚本:深入解析与优化技术》 MetaTrader 4(MT4)是一款广泛应用于外汇、期货和股票交易的交易平台,它提供了丰富的技术分析工具和自动化交易功能。在MT4平台中,用户可以编写...
《SpringBoot2深度解析——基于atguigu_springboot2_zz-master项目实践》 SpringBoot作为现代化Java开发的重要框架,极大地简化了Spring应用的初始搭建以及开发过程。本篇文章将深入探讨基于`atguigu_springboot2_...
基于国家标准的endnote的输出样式,适用于学生党论文插入文献参考,较为方便。endnote论文神器。
《制冷与空调设备组装与调试赛项:中职技能大赛深度解析》 ...总的来说,"ZZ-2022018 制冷与空调设备组装与调试赛项"是促进中职教育与产业需求紧密对接的重要途径,对于提升职业教育质量具有深远意义。
- 赛项编号:ZZ-2021009 - 英文名称:Parts Measurement & Modeling & Drafting Competition - 赛项组别:中职组 - 赛项归属产业:加工制造类 2. 竞赛目的: - 贯彻国家关于加快发展现代职业教育的决定和国家职业...
2023年的ZZ058动漫制作赛项赛题是这个领域的一次重要竞赛,聚焦于动画创作的技术与艺术融合,旨在检验参赛者在动漫制作领域的综合技能。 动漫制作是一个涵盖广泛领域的专业,包括故事构思、角色设计、场景设定、...
ZZ8L-2.5(4)型煤电钻综合保护装置是一种专为煤矿作业设计的安全设备,旨在确保煤电钻操作过程中的人员安全和设备稳定性。该装置集成了多种保护功能,包括漏电保护、短路保护以及必要的电气隔离控制,以防止意外...
《中医大夫助理信息系统 zz-doctor 深度解析》 中医大夫助理信息系统“zz-doctor”是一款基于Android平台的应用程序,旨在为中医医生提供智能化、便捷化的诊疗辅助工具。通过深入剖析这款应用的源码,我们可以了解...
赛证融通指的是将赛项内容与职业技能等级证书《机械数字化设计与制造》相对接,通过教学、实训、认证、竞赛一体化促进技能人才成长。中高贯通则是指赛项内容在对接中职专业课程的同时,也与装备制造类、电子信息类的...
base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz base zz zz zz zz zz
再者,"第一PPT.url"是一个快捷方式文件,其目标可能是指向一个在线的PPT资源库或者是与"第一PPT"相关的网站。用户点击后,可以直接进入这个网站,查找更多类似的PPT模板或者其他相关资源,以便于进行更高效的工作。...
ZZ-2022031 计算机检测维修与数据恢复赛项赛题 中职赛项 适合正在准备技能大赛的人群
【标签】"android应用源码zz-do android应用源码"表明这是与Android应用开发相关的代码,"zz-do"可能是项目或应用的简写,可能代表“中医助手”或类似的含义。标签强调了这是可以被开发者参考、学习或修改的源代码,...
通过“ZZ-2022010 机器人技术应用赛项”,学生将有机会将理论知识与实际操作相结合,提高问题解决能力,培养创新思维。这样的比赛对于准备技能大赛的中职学生来说,是一次宝贵的实践经验,有助于他们在未来的职业...