摘要:地址面試必備最最最常見的面試題總結(jié)第一周一中的值傳遞和引用傳遞非常重要首先要明確的是對(duì)象傳遞數(shù)組類接口是引用傳遞,原始類型數(shù)據(jù)整型浮點(diǎn)型字符型布爾型傳遞是值傳遞。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置。
這里會(huì)分享一些出現(xiàn)頻率極其極其高的面試題,初定周更一篇,什么時(shí)候更完什么時(shí)候停止。
Github地址:https://github.com/Snailclimb/Java-Guide/blob/master/面試必備/最最最常見的Java面試題總結(jié)/第一周(2018-8-7).md
一 Java中的值傳遞和引用傳遞(非常重要)首先要明確的是:“對(duì)象傳遞(數(shù)組、類、接口)是引用傳遞,原始類型數(shù)據(jù)(整型、浮點(diǎn)型、字符型、布爾型)傳遞是值傳遞。”
那么什么是值傳遞和應(yīng)用傳遞呢?值傳遞是指對(duì)象被值傳遞,意味著傳遞了對(duì)象的一個(gè)副本,即使副本被改變,也不會(huì)影響源對(duì)象。(因?yàn)橹祩鬟f的時(shí)候,實(shí)際上是將實(shí)參的值復(fù)制一份給形參。)
引用傳遞是指對(duì)象被引用傳遞,意味著傳遞的并不是實(shí)際的對(duì)象,而是對(duì)象的引用。因此,外部對(duì)引用對(duì)象的改變會(huì)反映到所有的對(duì)象上。(因?yàn)橐脗鬟f的時(shí)候,實(shí)際上是將實(shí)參的地址值復(fù)制一份給形參。)
有時(shí)候面試官不是單純問你“Java中是值傳遞還是引用傳遞”是什么啊,騷年?而是給出一個(gè)例子,然后讓你寫出答案,這種也常見在筆試題目中!所以,非常重要了,請(qǐng)看下面的例子:
值傳遞和應(yīng)用傳遞實(shí)例 1. 值傳遞public static void main(String[] args) { int num1 = 10; int num2 = 20; swap(num1, num2); System.out.println("num1 = " + num1); System.out.println("num2 = " + num2); } public static void swap(int a, int b) { int temp = a; a = b; b = temp; System.out.println("a = " + a); System.out.println("b = " + b); }
結(jié)果:
a = 20 b = 10 num1 = 10 num2 = 20
解析:
在swap方法中,a、b的值進(jìn)行交換,并不會(huì)影響到num1、num2。因?yàn)椋琣、b中的值,只是從num1、num2的復(fù)制過來的。
也就是說,a、b相當(dāng)于num1、num2的副本,副本的內(nèi)容無論怎么修改,都不會(huì)影響到原件本身。
public static void main(String[] args) { int[] arr = {1,2,3,4,5}; change(arr); System.out.println(arr[0]); } public static void change(int[] array) { //將數(shù)組的第一個(gè)元素變?yōu)? array[0] = 0; }
結(jié)果:
1 0
解析:
無論是主函數(shù),還是change方法,操作的都是同一個(gè)地址值對(duì)應(yīng)的數(shù)組。 。因此,外部對(duì)引用對(duì)象的改變會(huì)反映到所有的對(duì)象上。
一些特殊的例子 1. StringBuffer類型傳遞// 測試引用傳遞:StringBuffer @org.junit.Test public void method1() { StringBuffer str = new StringBuffer("公眾號(hào):Java面試通關(guān)手冊(cè)"); System.out.println(str); change1(str); System.out.println(str); } public static void change1(StringBuffer str) { str = new StringBuffer("abc");//輸出:“公眾號(hào):Java面試通關(guān)手冊(cè)” //str.append("歡迎大家關(guān)注");//輸出:公眾號(hào):Java面試通關(guān)手冊(cè)歡迎大家關(guān)注 //str.insert(3, "(編程)");//輸出:公眾號(hào)(編程):Java面試通關(guān)手冊(cè) }
結(jié)果:
公眾號(hào):Java面試通關(guān)手冊(cè) 公眾號(hào):Java面試通關(guān)手冊(cè)
解析:
很多要這個(gè)時(shí)候要問了:StringBuffer創(chuàng)建的明明也是對(duì)象,那為什么輸出結(jié)果依然是原來的值呢?
因?yàn)樵?b>change1方法內(nèi)部我們是新建了一個(gè)StringBuffer對(duì)象,所以str指向了另外一個(gè)地址,相應(yīng)的操作也同樣是指向另外的地址的。
那么,如果將change1方法改成如下圖所示,想必大家應(yīng)該知道輸出什么了,如果你還不知道,那可能就是我講的有問題了,我反思(開個(gè)玩笑,上面程序中已經(jīng)給出答案):
public static void change1(StringBuffer str) { str.append("歡迎大家關(guān)注"); str.insert(3, "(編程)"); }2. String類型傳遞
// 測試引用傳遞:Sring @org.junit.Test public void method2() { String str = new String("公眾號(hào):Java面試通關(guān)手冊(cè)"); System.out.println(str); change2(str); System.out.println(str); } public static void change2(String str) { // str="abc"; //輸出:公眾號(hào):Java面試通關(guān)手冊(cè) str = new String("abc"); //輸出:公眾號(hào):Java面試通關(guān)手冊(cè) }
結(jié)果:
公眾號(hào):Java面試通關(guān)手冊(cè) 公眾號(hào):Java面試通關(guān)手冊(cè)
可以看到不論是執(zhí)行str="abc;"還是str = new String("abc");str的輸出的值都不變。
按照我們上面講“StringBuffer類型傳遞”的時(shí)候說的,str="abc;"應(yīng)該會(huì)讓str的輸出的值都不變。為什么呢?因?yàn)镾tring在創(chuàng)建之后是不可變的。
下面的程序輸出是什么?
public class Demo { public static void main(String[] args) { Person p = new Person("張三"); change(p); System.out.println(p.name); } public static void change(Person p) { Person person = new Person("李四"); p = person; } } class Person { String name; public Person(String name) { this.name = name; } }
很明顯仍然會(huì)輸出張三。因?yàn)?b>change方法中重新創(chuàng)建了一個(gè)Person對(duì)象。
那么,如果把 change方法改為下圖所示,輸出結(jié)果又是什么呢?
public static void change(Person p) { p.name="李四"; }
答案我就不說了,我覺得大家如果認(rèn)真看完上面的內(nèi)容之后應(yīng)該很很清楚了。
二 ==與equals(重要)== : 它的作用是判斷兩個(gè)對(duì)象的地址是不是相等。即,判斷兩個(gè)對(duì)象是不是同一個(gè)對(duì)象。(基本數(shù)據(jù)類型==比較的是值,引用數(shù)據(jù)類型==比較的是內(nèi)存地址)
equals() : 它的作用也是判斷兩個(gè)對(duì)象是否相等。但它一般有兩種使用情況:
情況1:類沒有覆蓋equals()方法。則通過equals()比較該類的兩個(gè)對(duì)象時(shí),等價(jià)于通過“==”比較這兩個(gè)對(duì)象。
情況2:類覆蓋了equals()方法。一般,我們都覆蓋equals()方法來兩個(gè)對(duì)象的內(nèi)容相等;若它們的內(nèi)容相等,則返回true(即,認(rèn)為這兩個(gè)對(duì)象相等)。
舉個(gè)例子:
public class test1 { public static void main(String[] args) { String a = new String("ab"); // a 為一個(gè)引用 String b = new String("ab"); // b為另一個(gè)引用,對(duì)象的內(nèi)容一樣 String aa = "ab"; // 放在常量池中 String bb = "ab"; // 從常量池中查找 if (aa == bb) // true System.out.println("aa==bb"); if (a == b) // false,非同一對(duì)象 System.out.println("a==b"); if (a.equals(b)) // true System.out.println("aEQb"); if (42 == 42.0) { // true System.out.println("true"); } } }
說明:
String中的equals方法是被重寫過的,因?yàn)閛bject的equals方法是比較的對(duì)象的內(nèi)存地址,而String的equals方法比較的是對(duì)象的值。
當(dāng)創(chuàng)建String類型的對(duì)象時(shí),虛擬機(jī)會(huì)在常量池中查找有沒有已經(jīng)存在的值和要?jiǎng)?chuàng)建的值相同的對(duì)象,如果有就把它賦給當(dāng)前引用。如果沒有就在常量池中重新創(chuàng)建一個(gè)String對(duì)象。
三 hashCode與equals(重要)面試官可能會(huì)問你:“你重寫過 hashcode 和 equals 么,為什么重寫equals時(shí)必須重寫hashCode方法?”
hashCode()介紹hashCode() 的作用是獲取哈希碼,也稱為散列碼;它實(shí)際上是返回一個(gè)int整數(shù)。這個(gè)哈希碼的作用是確定該對(duì)象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味著Java中的任何類都包含有hashCode() 函數(shù)。
散列表存儲(chǔ)的是鍵值對(duì)(key-value),它的特點(diǎn)是:能根據(jù)“鍵”快速的檢索出對(duì)應(yīng)的“值”。這其中就利用到了散列碼!(可以快速找到所需要的對(duì)象)
為什么要有hashCode我們以“HashSet如何檢查重復(fù)”為例子來說明為什么要有hashCode:
當(dāng)你把對(duì)象加入HashSet時(shí),HashSet會(huì)先計(jì)算對(duì)象的hashcode值來判斷對(duì)象加入的位置,同時(shí)也會(huì)與其他已經(jīng)加入的對(duì)象的hashcode值作比較,如果沒有相符的hashcode,HashSet會(huì)假設(shè)對(duì)象沒有重復(fù)出現(xiàn)。但是如果發(fā)現(xiàn)有相同hashcode值的對(duì)象,這時(shí)會(huì)調(diào)用equals()方法來檢查hashcode相等的對(duì)象是否真的相同。如果兩者相同,HashSet就不會(huì)讓其加入操作成功。如果不同的話,就會(huì)重新散列到其他位置。(摘自我的Java啟蒙書《Head fist java》第二版)。這樣我們就大大減少了equals的次數(shù),相應(yīng)就大大提高了執(zhí)行速度。
hashCode()與equals()的相關(guān)規(guī)定如果兩個(gè)對(duì)象相等,則hashcode一定也是相同的
兩個(gè)對(duì)象相等,對(duì)兩個(gè)對(duì)象分別調(diào)用equals方法都返回true
兩個(gè)對(duì)象有相同的hashcode值,它們也不一定是相等的
因此,equals方法被覆蓋過,則hashCode方法也必須被覆蓋
hashCode()的默認(rèn)行為是對(duì)堆上的對(duì)象產(chǎn)生獨(dú)特值。如果沒有重寫hashCode(),則該class的兩個(gè)對(duì)象無論如何都不會(huì)相等(即使這兩個(gè)對(duì)象指向相同的數(shù)據(jù))
寫在最后 推薦一個(gè)自己的開源的后端文檔Java-Guide: Java面試通關(guān)手冊(cè)(Java學(xué)習(xí)指南)Java Interview Customs Manual (Java Study Guide)。star:1.4k。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76647.html
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...
閱讀 1239·2021-11-11 16:55
閱讀 1537·2021-10-08 10:16
閱讀 1188·2021-09-26 10:20
閱讀 3569·2021-09-01 10:47
閱讀 2451·2019-08-30 15:52
閱讀 2682·2019-08-30 13:18
閱讀 3194·2019-08-30 13:15
閱讀 1115·2019-08-30 10:55