正確理解Java方法的返回值

首先來看一段代碼

我們把這段代碼稱爲代碼①,接下來我們再來看另外一段代碼

我們把這段代碼稱爲代碼②。

在代碼①當中,定義了一個方法,這個方法聲明的返回值類型是double,而實際通過return關鍵字返回的卻是一個int型的值,但並沒有引起編譯錯誤。而在代碼②當中,情況正好相反,方法聲明的返回值類型是int,方法內部的return關鍵字實際返回了一個double類型的值,在這種情況下,編譯器卻報出了語法錯誤。

對比一下這兩種情況,很多初學Java的小夥伴搞不清:爲什麼同樣是方法聲明的返回值類型與實際返回值的類型不相同,第一種情況不報錯,而另一種情況卻無法通過編譯檢查呢?要講清楚這個問題,我們必須從爲什麼方法要聲明返回值類型說起。

在Java語言中,要求程序員在定義一個方法的時候,必須在方法名稱的前面聲明這個方法的返回值類型。爲什麼要求你這麼做呢?簡單來說,就是編譯器強制程序員必須公開一個信息,那就是:這個方法在運行之後會返回一個什麼類型的值,只有這樣,調用方法的人才知道要用一個什麼類型的變量接收方法的運算結果。除此之外,編譯器還要求:主調方法在接收返回值的過程中,必須以聲明的返回值類型作爲準,而不是看實際返回值的類型。就拿代碼①來說,聲明的返回值類型是double,實際返回值是int,我們在程序中用變量接收方法返回值的時候,必須用double型變量接收,即便是它實際返回的只是一個int型數據,也不能用int型變量接收返回值,否則就會出現編譯錯誤

 

接下來,我們再來觀察方法的定義過程。在代碼①當中,方法所聲明的返回值類型是double型,而實際在方法的內部返回的是一個int型的值,二者之間類型並不一致,但並沒有出現語法錯誤,這又是怎麼回事呢?這是因爲,Java語言在做語法檢查的時候,要求只要實際的返回值類型能夠”自動轉換”爲方法所聲明的返回值類型即可,並不要求二者必須完全相同。代碼①當中的方法,實際返回值是int類型的,它可以自動轉換爲一個double類型的值。而代碼②當中的方法,實際返回值是double類型的,無法自動轉換成int類型,所以報錯了。專業上,我們把編譯器可以自動完成的類型轉換也稱之爲“隱式類型轉換”。

爲了說明爲什麼方法聲明的返回值爲double類型,但實際卻可以在方法中返回一個int型的數據,我們來舉個容易理解的例子:你小的時候,你爸爸要出門,告訴你在他回來的時候會帶回一個直徑50釐米的大蛋糕,那麼你肯定會按照他的承諾,準備一個直徑50釐米的大盤子用來裝這個大蛋糕。但你爸爸回來的時候,實際帶回來的卻是一個直徑只有10釐米的小蛋糕,這時雖然你很傷心也很失望,但是,你所準備的大盤子足夠能放得下你爸爸帶回來的小蛋糕,不會出什麼問題。代碼①當中定義的方法就屬於這種情況,聲明返回一個佔8字節的double型數據,但實際返回一個佔4字節的int型數據。

但是反過來,你爸爸出門的時候告訴你他回來的時候會帶回一個10釐米的小蛋糕,你也按照他的承諾準備了一個直徑10釐米的小盤子,打算用來裝這個小蛋糕。但當你爸爸回來的時候,帶回的卻是一個直徑達50釐米的大蛋糕!這時,你又驚喜又激動,但是卻無法解決一個問題:你所準備的小盤子根本無法盛放這麼大的蛋糕!這就好比是代碼②中所展現的情況,聲明返回一個只佔4字節的int型數據,而方法運行實際返回一個8字節的double型數據,讓那些準備用int型變量接收方法返回值的人感到“措手不及”。當然,這只是一句玩笑,如果真的出現了實際返回值無法自動轉換成聲明的類型,編譯器根本不允許這樣的代碼通過編譯,所以也更談不上運行代碼了。

接下來再具體說說哪些情況下,編譯器能夠自動把一種類型”自動轉換”成另一種類型,也就是實現我們所說的”隱式類型轉換”。我們可以分以下幾種情況討論:

一、我們知道,Java基礎數據類型有8種,其中整數類型有4中,分別是long、int、short和byte。這4種整數類型有着明顯的“向下兼容”的特性,也就是說,較小的數據類型都可以自動轉換爲較大的數據類型,比如int類型的數據在賦值給long類型的變量時,可以自動完成從int到long的轉換。因此,聲明返回值爲較大的數據類型,實際返回較小的數據類型,是肯定沒有問題。比如,聲明返回值爲long類型,但實際返回int型數據是完全可以的。在這種情況下,int型的數據返回到主調方法中,在賦值給一個long類型的變量時,可以自動完成類型轉換。同樣,兩種浮點數double和float也能夠做到“向下兼容”,聲明double型,返回float型也完全可以。

二、我們還知道,表示字符的char類型,在實際存儲數據的過程中,存儲的也是一個佔兩個字節的”整數”,這個”整數”其實就是字符的編碼值。那麼char類型的數據能否與Java的4種整型完成自動類型轉換呢?實際情況是:char可以自動轉換爲long和int,但不能自動轉換爲short和byte。反過來,short和byte也不能自動轉換爲char。說的直白一點,就是如果我們把方法的返回值聲明爲char類型,方法實際返回的是long、int、short和byte型的數據都不行。

三、任意整型和字符型都可以自動轉換爲浮點型,但反之不成立。也就是說, long、int、short、byte以及char都可以自動轉換爲double和float。但反過來,double和float都無法自動轉換成long、int、short、byte以及char。這裏可能有寫小夥伴會有一點疑惑:8個字節的long類型數據真的能自動轉換爲4個字節的float型嗎?從語法的角度是沒有問題的,我們把一個long類型的數據賦值給一個float類型的變量不需要做強制類型轉換,編譯器也不會報錯。但實際存儲過程中,有可能會導致數據損失精度。注意,這裏所說的是“有可能”損失精度,而不是”一定”損失精度。

四、boolean類型在8種基礎數據類型中是”特立獨行”的,它無法與任何其他基礎類型的數據完成相互自動轉換的操作,如果一個方法聲明返回值類型爲boolean,那麼這個方法只能返回boolean類型的數據,返回任何其他基礎數據類型的值都會報錯。

 

以上我們談到的方法返回值都是基礎數據類型,如果是引用數據類型,情況又如何呢?這種情況下,遵循“子類對象可以自動轉爲父類對象”的原則。也就是說,如果返回值被聲明爲父類,而實際返回對象爲子類對象,完全可以順利通過編譯器語法檢查。同樣,如果返回值類型被聲明爲接口,方法實際返回對象爲接口的實現類對象,也沒有問題。而反過來,方法聲明返回值類型爲子類,實際返回值爲父類對象是無法通過編譯檢查的。

希望本文對初學Java的小夥伴理解方法的返回值有所幫助。

如想系統學習Java編程,可以點擊這裏觀看我在本站的視頻課程,有問題也可以加入我的QQ羣291839907一起討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章