Java開發中論JDK源碼的重要性:一道經典面試題引發的無限思考
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
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小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
結果為:true
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
結果為:true
結果為:false
那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。
哈哈哈。
那麼我們怎麼解決最後的問題:(最初的面試問題)
1.
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
結果為:true
結果為:false
那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。
哈哈哈。
那麼我們怎麼解決最後的問題:(最初的面試問題)
1.
2.
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
結果為:true
結果為:false
那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。
哈哈哈。
那麼我們怎麼解決最後的問題:(最初的面試問題)
1.
2.
3.取巧的方式:
論JDK源碼的重要性:一道面試題引發的無限思考
大家在看到這個標題時想的是什麼?小編我為什麼要講這個問題呢?
有兩個原因:1.因為小編以前也被類似的問題坑過,雖然說現在小編是老司機,但是老司機以前也犯過一些錯誤,也是跟有些同學們一樣從一名小白一步一步趟坑趟過來的。那麼現在的話,作為一名合格的老司機,我要把這些坑分享給大家,讓你們如果遇到這個面試題或者這個問題,能夠回答的遊刃有餘。對吧。
2小編之前看到有人問到過這個問題,而且也有他給出過各種解決方案,但是小編相信大部分人拿到這個解決方案以後,並不知道他的原理是什麼,那麼不懂原理,過一段時間就會忘記。所以小編我把這道題拿出來做一個技術分享。
好,那麼,這道面試題是什麼呢?我們來看:差不多是這樣子的面試題
題目的意思是:定義了兩個Integer類型變量,通過swap方法交換這兩個變量的值。請寫出swap的代碼實現。
題目就是這樣清楚,簡單。但是看似簡單,大部分同學如果第一次遇到,不一定能夠寫出來。
那麼,請問:這道題,怎麼破?是吧哈
有沒有人知道,來,自告奮勇把你的亮劍亮出來,破了他。 那麼,到底怎麼解?
好的,看似簡單的題目,是不是不知道從何下手,我猜想有些大家第一想到的是這樣的解法:來看代碼:
有人肯定會通過這種方式來做,是不是,你們認為這樣可行嗎?我們來run一把看看結果:
從結果來看是錯誤的,不能解決我們的問題。為什麼? 這裡是今天要講的第一個知識點:
Java的傳值
在java中,有兩種傳值方式:(筆記)
一種是按值傳遞,一種是引用傳遞
那麼,按值傳遞意味著將當前的參數傳遞給方法的時候,方法中的變量接收的是傳過來變量的副本值(相當於拷貝了一份值),因此,我們修改了方法裡面的變量的值,並不會改變外
面變量的值。
引用傳遞:傳遞的是指向值的地址的指針
那麼,請問大家,這裡是按值傳遞 還是 引用傳遞?好,老司機告訴你們,這裡是按值傳遞,為什麼?Integer不是對象嗎? 對象傳遞不是傳遞的指針嗎?大家有沒有去看過Integer類的源碼,看看這個類是怎麼定義的,我們來看下,實際上面Integer使用的final定義的,也就意味著通過Integer實例化的對象是不能改變的,跟String是不是差不多。所以這裡的話,是傳遞的值,我們來畫下圖:
那麼,java中的內存主要分為兩塊把:堆和棧,棧存儲變量本身,堆存儲對象的值,然後通過棧執行堆內存地址來建立關係。是吧 。
通過swap方法後:意味著,會同樣創建兩個變量num1和num2,他們的值是剛剛拷貝過來的ab的值,此時內存中時怎麼變化的呢:
大家,知道為什麼會有地址指針這個東西,主要是我們的堆內存他主要是存儲的是一些對
象,對象是最佔內存的,為了能夠節省對內從的空間,就出現了這種概念。
好,講到這裡,至少大家應該清楚了一點:引用傳遞和按值傳遞的不同。
我們再來看,這個Integer他內部是如何賦值的,我們來看下:進入Integer類
Ctrl+o搜索Integer構造方法:
然後我們發現這個value定義的是final類型的:
如果他有一個setValue()的方法的話,那麼我們是是不是可以通過這個方法來改變值,但是Integer並沒有提供。也就是說這種方法是行不通的,好,那麼我們今天講到第二個知識點:反射
有沒有人在做這個題目的時候有沒有想過用反射來實現?
有想過的,看有多少人有往這個方面去想,
我們剛剛看到Integer類中存在一個value值變量嗎?對吧,所以我們需要拿到這個value變量然後來改變他的值,對吧,那麼我們怎麼來做,我們可以通過反射的方式拿到這個變量,這個Filed,然後去改變他的值,對吧。我們來看下怎麼寫:
理論上來說,這種方式是一定能夠實現我們的要求的
Run下:報錯:“Class com.edu.example.test.Test can not access a member of class java.lang.Integer with modifiers "private final"”
報錯了,是不是,那麼這又是另外一個知識點:
私有的成員屬性是不能通過反射來賦值的
那麼,如果要強攻,怎麼辦?實際上面,在java反射中,提供了一個叫設置訪問權限的東西,我們進入Field類中看下:
然後他裡面有一個setAccessible的方法:
這個方法就是用來設置成員屬性訪問權限的。我們看到最後是給obj.override=flag
那麼我們在回過頭來看下,Field的set方法:
這幾行代碼意味著,也就是說,如果override是false,就會調用Reflection.quickCheckMemberAccess(clazz, modifiers)來檢查成員屬性的訪問權限。
所以說,我們再來看,這個時候是不是就可以通過設置setAccessible(true)為true來標誌不需要訪問權限的檢查。這樣就可以修改value的值了。對不。
我們來試驗下:
好,大家覺得這樣沒問題
結果如下:
結果是,a的值確實變了,但是b的值卻沒有變,首先說明通過這種方式確實可以改變值,但是為什麼b的值沒有變化呢?。請問為什麼?
我們再回過頭來看看外面的方法,檢查一下,我們定義了:
有沒有發現什麼問題?
Integer是不是一個封裝類型,而他的值1,2,是不是一個int類型,是一個基本數據類型,那麼這裡是怎麼賦值的呢? 那麼我們按照正常來寫是不是這樣子的:
int a = 1;
但是為什麼使用Integer也不會報錯了,好,這就講到了我們又一個知識點:(筆記)
Java中的裝箱和拆箱
那麼我們來實際看下,我們耳聽為虛,眼見為實,我們來看下編譯的字節碼文件:
命令:javap -c Test.class
可以看到:
Jvm他自動做了裝箱操作,看的清清楚楚對吧,對吧
好那麼,我們來看下Integer.valueOf(1):源碼
意味著值大於IntegerCace.low小於IntegerCache.high的話:
會從IntegerCache中獲取,也就是從緩存中取值。
那麼我們來看下IntegerCache:
也就是說從-128到127直接的所有值,都是從緩存中獲取。而緩存中的值,是什麼時候放進去的,是jvm啟動的時候就放進去了,然後分配好內存地址。
你們有沒有發現,就短短几行代碼,怎麼就有這麼多知識,是不是都有點感覺不認識java了。很神奇吧,哈哈
好,前面這兩行代碼我們分析完了對吧,好,然後,然後我們把ab的值傳進來,我們再來分析swap中的這段代碼,好吧,精華部分就是這段代碼了啊,這是精華部分,
哈哈,我們來看:斷點到這句
然後按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
第三步:下一行代碼執行
此時,再次拿出IntegerCache, 那麼下標為129,130的值都變成了2, 此時tmp的值為1,那麼從IntegerCache獲取到的值為IntegerCache[1+128=129] ,也就是獲取130行的數,也就是2
所以結果就是這樣。
實際上面和下面這個是一樣的:
從這一句debug進去:發現走的緩存,然後從cache中第129個下標找到了。
所以,當我們的值是在【-127-128】的時候,他是從IntegerCache中獲取的
其實,我們可以這樣來驗證一下:
結果為:true
結果為:false
那麼,這個當時我其實又遇到這個坑,被坑慘了是吧。
哈哈哈。
那麼我們怎麼解決最後的問題:(最初的面試問題)
1.
2.
3.取巧的方式:
好啦。,今天get到東西的,給我來一波贊,學到東西的,給我來一波訂閱關注喔,如果沒有聽懂的,也沒有關係,可以加入我技術交流群469717771驗證:頭條,獲取今天的講的內容的視頻或者往期的視頻,拿去慢慢的消化思考。