java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:true

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:true

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:false

那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。

哈哈哈。

那麼我們怎麼解決最後的問題:(最初的面試問題)

1.

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:true

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:false

那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。

哈哈哈。

那麼我們怎麼解決最後的問題:(最初的面試問題)

1.

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

2.

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:true

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:false

那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。

哈哈哈。

那麼我們怎麼解決最後的問題:(最初的面試問題)

1.

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

2.

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

3.取巧的方式:

論JDK源碼的重要性:一道面試題引發的無限思考

大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?

有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。

2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。

好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。

題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。

那麼,請問:這道題,怎麼破?是吧哈

有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?

好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:

Java的傳值

在java中,有兩種傳值方式:(筆記)

一種是按值傳遞,一種是引用傳遞

那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外

面變量的值。

引用傳遞:傳遞的是指向值的地址的指針

那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:

那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對

象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。

好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。

我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類

Ctrl+o搜索Integer構造方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後我們發現這個value定義的是final類型的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射

有沒有人在做這個題目的時候有沒有想過用反射來實現?

有想過的,看有多少人有往這個方面去想,

我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

理論上來說,這種方式是一定能夠實現我們的要求的

Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”

報錯了,是不是,那麼這又是另外一個知識點:

私有的成員屬性是不能通過反射來賦值的

那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後他裡面有一個setAccessible的方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag

那麼我們在回過頭來看下,Field的set方法:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。

所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。

我們來試驗下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好,大家覺得這樣沒問題

結果如下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?

我們再回過頭來看看外面的方法,檢查一下,我們定義了:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

有沒有發現什麼問題?

Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:

int a = 1;

但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)

Java中的裝箱和拆箱

那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:

命令:javap -c Test.class

可以看到:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧

好那麼,我們來看下Integer.valueOf(1):源碼

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

意味著值大於IntegerCace.low小於IntegerCache.high的話:

會從IntegerCache中獲取,也就是從緩存中取值。

那麼我們來看下IntegerCache:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈

好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,

哈哈,我們來看:斷點到這句

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

然後按F5進去看下,把IntegerCache裡面的值全面拿出來放到notepat++

第一步:是不是需要獲取num2的值,那麼他從下標[2+128=130]IntegerCache中獲取值為:130下標,也就是第131個數字為:2

第二步:field.set(num1,num2),, 意味著第一步先獲取num1在IntegerCache中的值IntegerCache[1+128] =1 ,然後會修改IntegerCache[num1]的值為num2從Integercache中獲取到的值2, 也就是修改為:integerCache[129] = 2

第三步:下一行代碼執行

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2

所以結果就是這樣。

實際上面和下面這個是一樣的:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的

其實,我們可以這樣來驗證一下:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:true

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

結果為:false

那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。

哈哈哈。

那麼我們怎麼解決最後的問題:(最初的面試問題)

1.

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

2.

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

3.取巧的方式:

java大型互聯網公司經典面試題,論JDK源碼的重要性的無限思考

好啦。,今天get到東西的,給我來一波贊,學到東西的,給我來一波訂閱關注喔,如果沒有聽懂的,也沒有關係,可以加入我技術交流群469717771驗證:頭條,獲取今天的講的內容的視頻或者往期的視頻,拿去慢慢的消化思考。

相關推薦

推薦中...