日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

为什么说 Java 是按值传递的?

發(fā)布時間:2024/4/13 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 为什么说 Java 是按值传递的? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么說 Java 是按值傳遞的?

  • 按值傳遞與按引用傳遞
  • Java 的按值傳遞
  • Java 的“傳引用”
  • C++ 中的引用與指針
  • 總結(jié)

??很多人認(rèn)為 Java 是按引用傳遞的。一方面,Java 有引用(reference)的概念。另一方面,可以通過函數(shù)形參修改函數(shù)外的某對象的字段,這看起來像是引用的特性。但實際上,Java 是按值傳遞的。這一點可以在官方及很多的權(quán)威書籍上得到印證,而且,Java 只有按值傳遞。

??如果對 Java 已經(jīng)使用得非常熟練,對此理解不透徹也無傷大雅。不過很多行業(yè)最終都會要求專業(yè)性,對基本的概念分不清楚會降低威信力。那么,為什么說Java是按值傳遞的呢?

按值傳遞與按引用傳遞

??首先需要知道什么是按值傳遞(pass-by-value),什么是按引用傳遞(pass-by-reference)。無論是按值傳遞還是按引用傳遞,都是針對實參來說的。如果在傳參過程中,形參得到的是實參的,那么就是按傳遞。如果得到的是實參的引用,那么就是按引用傳遞。

Java 的按值傳遞

??Java 的按值傳遞之所以令人疑惑是因為 Java 的變量語法。Java 中的非匿名變量有兩種,一種是 基本類型變量、另一種是 對象引用變量。問題是 基本類型變量 的值直接是我們一般想要使用的數(shù)據(jù),但 對象引用變量 不是這樣,它儲存的是某個匿名對象的引用。對象引用變量 的值 匿名對象的引用 不是我們直接需要的,我們直接需要的是這個匿名對象內(nèi)部的數(shù)據(jù)——它的字段、它的方法等。注意,對象引用變量 的值和它引用的匿名對象內(nèi)部的數(shù)據(jù)不是同一個概念。修改一個 對象引用變量 指向的匿名對象的字段,不等于修改這個 對象引用變量 的值。

??這個難以完全使用文字來描述清楚,筆者畫了一個創(chuàng)建對象時的示意圖如下。

??也就是說,在 Java 中,只能得到一個對象的引用,而得不到這個對象本身(但對于 基本類型,如果不考慮 Java 虛擬機的優(yōu)化的話,在創(chuàng)建時的這個變量,就是這個變量本身。)。現(xiàn)在,讓我們來看一個函數(shù)調(diào)用和傳參的過程。

public class Main {class DemoClass {int demoField;public void setDemoField(int fieldValue) {this.demoField = fieldValue;}public int getDemoField() {return this.demoField;}}public static void demoFun(DemoClass formPara) {formPara = null;}public static void main(String[] args) {DemoClass demoObject = new DemoClass();demoObject.setDemoField(666);demoFun(demoObject); // 這會讓 demoObject 的值變成 null 嗎?// 這行代碼會因“空引用”引發(fā)異常,還是輸出 666 呢?System.out.println(demoObject.getDemoField());// TODO} }

??請注意圖中代碼的注釋,調(diào)用 demoFun(demoObject) 會讓 demoObject 的值變成 null 嗎?有經(jīng)驗的老手可能直接使用直覺判斷出 demoObject 的值不會為 null ,盡管也許說不出原因。實際上,這就是按值傳遞的結(jié)果。通過函數(shù)調(diào)用 demoFun(demoObject),函數(shù) demoFun 的形參 formPara 獲得了實參 demoObject 的值,也就是匿名 DemoClass 對象的引用。因此,formPara 并不是 demoObject 的引用,所以修改不了 demoObject 的值,因此 demoObject 的值還為 null。也就是說,雖然 Java 有引用的概念,但不存在按引用傳遞。

??下面的這段代碼也同樣提醒了這一點。

public class Main {class DemoClass {int demoField;public void setDemoField(int fieldValue) {this.demoField = fieldValue;}public int getDemoField() {return this.demoField;}}public static void main(String[] args) {DemoClass demoObject = new DemoClass();demoObject.setDemoField(666);DemoClass otherReferVar = demoObject;otherReferVar = null; // 這會讓 demoObject 的值變成 null 嗎?// 這行代碼會因“空引用”引發(fā)異常,還是輸出 666 呢?System.out.println(demoObject.getDemoField());// TODO} }

Java 的“傳引用”

??還有一個在 Java 中流行使用的口語化詞匯:傳引用。由于此詞匯廣泛使用,因此這里不質(zhì)疑它的合法性。那么,既然“傳引用”是正確的,為什么前面又說 Java 是按值傳遞的呢?請注意,“傳引用”中的“引用”與“按引用傳遞”中的“引用”指的不是同一個概念。在“傳引用”中,只要中間有某個過程傳遞的是引用,就認(rèn)為這是在“傳引用”。比如,上面的函數(shù)調(diào)用 demoFun(demoObject) 中,函數(shù) demoFun 的形參 formPara 獲得了實參 demoObject 的值,也就是匿名DemoClass對象的引用。雖然此過程是傳遞的是實參 demoObject 的值(按值傳遞),但 demoObject 的值正好是匿名 DemoClass 對象的引用,因此此過程也可以稱之為“傳引用”。記住,在術(shù)語按值傳遞、引用傳遞中,衡量標(biāo)準(zhǔn)都嚴(yán)格要求是實參。而在 Java 中,永遠也無法通過函數(shù)調(diào)用直接修改實參的值。

C++ 中的引用與指針

??雖然有引用的概念不代表函數(shù)調(diào)用時按引用傳遞,但不是什么編程語言的引用都只能按值傳遞的。比如 C++ 中的引用,可以按值傳遞,也可以按引用傳遞,這取決于定義調(diào)用函數(shù)的定義,而和實參是不是引用無關(guān)。而 JavaScript 中的引用和 Java 一樣,只能按值傳遞。

??不過,在此處筆者還要糾正一下,C++ 中的引用與 Java 中的引用從性質(zhì)上來說是不同的。Java 中的引用更像是 C++ 中的指針。也就是說,C++ 中的引用與 C++ 中的指針不是同一個性質(zhì)的概念。有的“自認(rèn)為喜歡鉆研”的人喜歡吹捧自己的“獨特見解”:C++ 中的引用在內(nèi)部原理上可以由指針來實現(xiàn),因此 C++ 中的引用與指針是一碼事。這個觀點算不上開闊。內(nèi)部原理如何與概念是否相同無關(guān)。從設(shè)計模式來說,同一個問題可以由不同的設(shè)計模式來實現(xiàn),不代表實現(xiàn)這個問題的所有的設(shè)計模式本質(zhì)上都是相同的,更不代表這個問題就是一種設(shè)計模式,且與實現(xiàn)它的設(shè)計模式相同。C++ 的指針變量被賦值時,這個指針之前指向的對象不受影響,但 C++ 的引用就不同了。C++ 的引用變量在創(chuàng)建之后就幾乎與其引用的對象完全相同。

??有的人認(rèn)為 C++ 中的指針與 Java中的引用不同,理由是 C++ 的指針與 C++ 其它普通的類型的量綱不一致。確實如此。不過,這只是因為 C++ 中存在非匿名的對象。如果這類人對聲明指針時使用的星號 * 非常敏感,C++ 中還提供了關(guān)鍵字 typedef。該關(guān)鍵字專門為有“整體”數(shù)學(xué)思想的人提供。如果拒絕使用非匿名的對象(只使用關(guān)鍵字 new 創(chuàng)建對象),且使用關(guān)鍵字 typedef 消除使用指針時必定使用的解引用運算符 *,這些人將會驚奇的自我發(fā)問:自己使用的究竟是哪門語言。

總結(jié)

(左值創(chuàng)建、右值創(chuàng)建指的是創(chuàng)建變量時位于賦值運算符 = 的左右還是右邊)

  • Java:

    • 只能按值傳遞。

    • 對象都是匿名的。右值創(chuàng)建。創(chuàng)建對象時返回其引用。

    • 基本類型變量都是非匿名的。左值創(chuàng)建。匿名的基本類型都是常量。

  • JavaScript:同 Java。

  • C++:

    • 可按值傳遞,也可按引用傳遞。傳遞規(guī)則與目標(biāo)是基本類型還是對象無關(guān)。

    • 變量和對象可匿名創(chuàng)建,也可不匿名創(chuàng)建。可左值創(chuàng)建,也可右值創(chuàng)建。創(chuàng)建匿名變量和對象時返回其指針值。

  • C:只能按值傳遞。無對象。其它同 C++。

總結(jié)

以上是生活随笔為你收集整理的为什么说 Java 是按值传递的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。