Java中值類型和引用類型詳解

我們都知道java是一種面向對象的編程語言,但是在實際意義上java並不是純面向對象,因為面向對象的意義就是萬物皆對象,那麼如果說int類型的變量也是一個對象的話,那麼我們應該能用"."這個東西訪問到它的屬性或者是方法,例如:

import java.util.ArrayList;
import java.util.List;
 
public class Test {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.get(0);
    }
}

就好比是這樣,我們把這個list這個對象看做一個變量,如果他是對象的話那麼我們應該能夠訪問到它的屬性和方法,但是在java中的基本數據類型是沒屬性和方法的,那麼我們就可以說,隻要點"."不出來東西的變量都是基本數據類型(於是就出現瞭包裝類這種東西)。

關於java中的值類型和引用類型的方法傳遞問題

咱們先看看Java中的這些數據是怎麼存儲的

不知道兄弟們能不能理解,我在用語言描述一遍

在一個函數中兩個基本類型的變量在聲明瞭之後,將這兩個變量作為參數傳遞給另一個方法,這個方法會復制兩個副本,也就是說在swap(int, int)方法中交換的是兩個副本的值,其真實的值並沒有交換,那麼就會有人想瞭,那用包裝類啊,用引用類型的數據不就能交換瞭嗎,咱麼看一下: 

public class Test {
    public static void main(String[] args) {
        Integer n1 = 1, n2 = 2;
        System.out.println("交換前: num1: " + n1 + "\tnum2: " + n2);
        swap(n1, n2);
        System.out.println("交換後: num1: " + n1 + "\tnum2: " + n2);
    }
    public static void swap(Integer num1, Integer num2) {
       Integer temp = num1;
       num1 = num2;
       num2 = temp;
    }
}

這個結果是沒有交換的,那麼就會有人想瞭,這是怎麼回事呢?

其實雖說是引用類型,但是在傳參數的過程中,還是按照副本的方式傳遞的,隻不過是將棧區中存儲的地址作為副本進行交換,但是數據在堆中,並沒有交換。

Oracle官方也說過,java是沒有引用傳遞的,隻有值類型的按值傳遞和引用類型的按值傳遞,說白瞭隻有按值傳遞,是無他將引用進行傳遞的。但是C++中是有引用類型的,我們來看一段代碼:

#include <iostream>
using namespace std;
 
int main(int agv, char** args)
{
	int num1 = 1, num2 = 2;
	cout << "交換前 " << "num1: " << num1 << "\tnum2: " << num2 << endl;
	swap(num1, num2);
	cout << "交換後 " << "num1: " << num1 << "\tnum2: " << num2 << endl;
}
 
void swap(int& num1, int& num2)
{
	int temp = num1;
	num2 = num1;
	num2 = temp;
}

結果顯示為:

這個是C++中的引用類型傳遞,傳遞的參數確確實實是數據的引用

在C++中或者利用指針進行地址中的值交換操作也可以,隻不過相對來說麻煩一些(其實這是在C中的操作)輸出結果和上面的是一樣的

#include <iostream>
using namespace std;
 
int main(int agv, char** args)
{
	int num1 = 1, num2 = 2;
	cout << "交換前 " << "num1: " << num1 << "\tnum2: " << num2 << endl;
	swap(num1, num2);
	cout << "交換後 " << "num1: " << num1 << "\tnum2: " << num2 << endl;
}
 
void swap(int* num1, int* num2)
{
	int temp = *num1;
	*num1 = *num2;
	*num2 = temp;

在C#中也有引用傳遞,需要用到關鍵字ref,代碼如下

        static void Main(string[] args)
        {
            int num1 = 1, num2 = 2;
            Console.WriteLine("交換前: num1: {0}\tnum2: {1}", num1, num2);
            swap(ref num1, ref num2);
            Console.WriteLine("交換後: num1: {0}\tnum2: {1}", num1, num2);
            Console.ReadKey();
        }
 
        static void swap(ref int num1, ref int num2)
        {
            int temp = num1;
            num1 = num2;
            num2 = temp;
        }

輸出結果為:

 確實也進行交換瞭

說瞭這麼多都快跑題瞭,這時候可能就有人想  誒 明明標題是Java的標題,怎麼說瞭這麼一大堆其他語言的東西,馬上瞭  不用著急

但是Java這兩個功能沒有怎麼辦呢?

我們可以用數組的方式,反正就是想法設法把堆中的數據進行交換,或者用返回值的方式,但是返回的話也隻能返回一個數據(不像C#中能返回多個數據,有人就會想瞭,怎麼java這麼菜,啥啥幹不瞭),但是事實就是如此,我們又能有什麼辦法。。。

    public static void main(String[] args) {
        int[] n1 = {1}, n2 = {2};
        System.out.println("交換前: num1: " + n1[0] + "\tnum2: " + n2[0]);
        swap(n1, n2);
        System.out.println("交換後: num1: " + n1[0] + "\tnum2: " + n2[0]);
    }
    public static void swap(int[] num1, int[] num2) {
        int temp = num1[0];
        num1[0] = num2[0];
        num2[0] = temp;
    }

所以咯,java隻能這麼進行交換瞭

到此這篇關於Java中值類型和引用類型詳解的文章就介紹到這瞭,更多相關Java值類型和引用類型內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: