每日幾道java新手入門面試題,通往自由的道路
面向過程:面向過程的編程方式,程序會將要完成的某一個任務(wù)拆解成一系列的小步驟 (函數(shù)),如:
① 打開洗衣機(jī):method01() ② 放入要洗的衣服:method02() ③ 放入洗衣服:method03() ④ 清洗:method04() ⑤ 烘干:method05()面向?qū)ο螅好嫦驅(qū)ο蟮木幊谭绞剑绦驎⒁瓿傻南匆聶C(jī)洗衣服的任務(wù)拆分成如下兩個對象:
人(Person):Person在洗衣機(jī)洗衣服這個程序任務(wù)中有三個作用,分別是打開洗衣機(jī)、放入要洗的衣服、放入洗衣粉。 洗衣機(jī)(Machine):Machine在洗衣機(jī)洗衣服這個程序任務(wù)中有兩個作用,分別是清洗、烘干。從上面這個例子能看出,面向過程的編程方式比較直接且高效,而面向?qū)ο蟮木幊谭绞礁讖?fù)用、擴(kuò)展和維護(hù)!
2、請你簡述一下面向?qū)ο蟮娜齻€基本特征?繼承:承是Java中面向?qū)ο笞铒@著的一個特征,繼承是從已有的類中派生出新的類,新的類可以吸收已有的屬性、行為,并擴(kuò)展新的能力。Java中不支持多繼承,但是接口可以支持多實現(xiàn)。
封裝:將同一類事物的特征和功能包裝在一起,只對外暴露需要調(diào)用的接口。封裝也稱為信息的隱藏,在Java中接口是體現(xiàn)封裝最常用的方法,在接口中我們沒有任何功能的實現(xiàn)(具體實現(xiàn)都交給實現(xiàn)類),只是定義了一系列抽象的方法聲明用于外部調(diào)用。
多態(tài):封裝和繼承都是為多態(tài)來服務(wù)的,多態(tài)是指同一個行為具有多個不同的表現(xiàn)形式。在Java中方法的重載和重寫是實現(xiàn)多態(tài)的2種方式。
重載發(fā)生在一個類中,同名的方法如果有不同的參數(shù)列表(參數(shù)類型不同、參數(shù)個數(shù)不同或者二者都不同)則視為重載。方法重載體現(xiàn)了編譯時的多態(tài)性。
重寫發(fā)生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,重載對返回類型沒有特殊的要求。方法重寫體現(xiàn)了運行時的多態(tài)性。 多態(tài)的三要素:繼承 、重寫、父類指向子類引用!3、為什么說 Java 是一種半解釋半編譯的程序設(shè)計語言呢?什么是編譯形語言,什么又是解釋形語言?
編譯型語言:把做好的源程序全部編譯成二進(jìn)制代碼的可運行程序。然后,就可以直接運行這個程序。執(zhí)行速度快,效率高,依靠編譯器,跨平臺性稍差。 解釋型語言:把已經(jīng)做好的源程序,翻譯一句,執(zhí)行一句,直到結(jié)束。執(zhí)行速度慢,效率低,依靠編譯器,但是跨平臺性稍好。那么為什么說Java 是編譯型語言呢?
第一個觀點認(rèn)為 Java 是編譯型語言,因為Java程序想要運行,那么第一步就是要使用Javac進(jìn)行編譯(將Java源文件編譯成.class二進(jìn)制文件)。沒有經(jīng)過編譯的.java文件,是沒辦法運行的!
那么為什么又說Java 是解釋型語言呢?
那么第二個觀點則是認(rèn)為Java是解釋型語言,Java經(jīng)過編譯,Javac 將.java源文件編譯成.class二進(jìn)制文件之后,仍然需要借助 JVM 的解釋執(zhí)行。
綜合上面兩個觀點來看,Java似乎既有編譯型語言的特點,又有解釋型語言的特點,也沒有看到哪本權(quán)威的書籍上認(rèn)定Java就是哪一種類型的語言。
4、請你說一下Java中的8大基本類型是那些?如圖所示:
8種基本數(shù)據(jù)類型和取值范圍:
基本類型 大小(位/bit) 字節(jié)數(shù)(byte) 最小值 最大值 默認(rèn)值 包裝器類型 boolean - - false true false Boolean char 16 bits 2 bytes Unicode 0 Unicode 2^16-1 空 Character byte 8 bits 1 byte -2^7 2^7-1 0 Byte short 16 bits 2 bytes -2~15 2^15-1 0 Short int 32 bits 4 bytes -2^31 2^31-1 0 Integer long 64 bits 8 bytes -2^63 2^63-1 0 Long float 32 bits 4 bytes 0.0 Fload double 64 bits 8 bytes 0.0 Double注意:對于boolean值,在Java規(guī)范中并沒有給出其儲存大小,在《Java虛擬機(jī)規(guī)范》中給出了4個字節(jié),和boolean數(shù)組1個字節(jié)的定義,具體還要看虛擬機(jī)實現(xiàn)是否按照規(guī)范來,所以1個字節(jié)、4個字節(jié)都是有可能的。除了void之外,其他8種基本數(shù)據(jù)類型被稱為八大基本數(shù)據(jù)類型。
圖中從左向右的轉(zhuǎn)換都是隱式轉(zhuǎn)換,無需再代碼中進(jìn)行強(qiáng)制轉(zhuǎn)換。從右向左均要進(jìn)行強(qiáng)制類型轉(zhuǎn)換,才能通過編譯。強(qiáng)制轉(zhuǎn)換會丟失精度。
5、請你講講抽象類和接口有什么區(qū)別?(一) 繼承方面:
抽象類只能單繼承;而接口可以多實現(xiàn);(二) 成員屬性方面:
抽象類中可以有普通屬性,也可以有常量; 接口中的成員變量全部默認(rèn)是常量,使用public static final修飾,這個可以省略不寫;(三) 代碼塊方面:
抽象類可以含初始化塊;接口不能含初始化塊;(四) 構(gòu)造函數(shù)方面:
抽象類可以有構(gòu)函數(shù),但是這里的構(gòu)造函數(shù)不是用來創(chuàng)建對象的,而且用來被實現(xiàn)類調(diào)用進(jìn)行初始化操作的; 接口不能有構(gòu)造函數(shù);(五) 方法方面:
接口在JDK1.8之后可以定義抽象方法(無方法體)、default 修飾的默認(rèn)方法(有方法體)、static修飾的靜態(tài)方法(有方法體),JDK1.8以前是只能有抽象方法。
public interface Test { static void test() { } default void test2(){ } void test3();// 默認(rèn)是abstract修飾 }
抽象類中除了靜態(tài)方法和抽象方法外還可以有普通方法。
二者相同之處
接口與抽象類都不能被實例化,需要被其他進(jìn)行實現(xiàn)或繼承。 接口與抽象類里面都能包含抽象方法,實現(xiàn)接口或繼承抽象類的子類都必須實現(xiàn)這些抽象方法。6、請判斷當(dāng)一個對象被當(dāng)作參數(shù)傳遞給一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?是值傳遞。java 編程語言只有值傳遞參數(shù)。當(dāng)一個對象實例作為一個參數(shù)被傳遞到方法中時,參數(shù)的值就是對該對象的引用。對象的內(nèi)容可以在被調(diào)用的方法中改變,但對象的引用是永遠(yuǎn)不會改變的。
java中只有值傳遞,基本類型傳遞的是值的副本,引用類型傳遞的是引用的副本
7、請你說一下JVM/JRE/JDK的區(qū)別?直接看一張圖就可以理解他們的區(qū)別了:
重載:方法重載發(fā)生在同一個類中,重載的方法之間方法名必須相同,參數(shù)列表不同(參數(shù)的類型、參數(shù)的個數(shù)),方法的返回值和訪問修飾符可以不同,發(fā)生在編譯時期(方法重載實現(xiàn)了編譯時多態(tài))。
重寫:方法重寫發(fā)生在子父類中,子類重寫父類的方法,方法名稱必須相同,參數(shù)列表也必須相同,方法的返回值小于等于父類方法的返回值,訪問修飾符方位大于等于父類方法(如果父類方法修飾符為private,則子類就無法重寫了)。
9、請你說一下List接口和Set接口的區(qū)別? List:有序、可重復(fù)集合。按照對象插入的順尋保存數(shù)據(jù),允許多個Null元素對象,可以使用iterator迭代器遍歷,也可以使用get(int index)方法獲取指定下標(biāo)元素。 Set:無序、不可重復(fù)集合只允許有一個Null元素對象,取元素時,只能使用iterator迭代器逐一遍歷。 Map: key-value 鍵值對形式的集合,添加或獲取元素時,需要通過key來檢索到value。Collecttion 集合體系結(jié)構(gòu)簡圖:
equals()只是判斷對象屬性是否相同,hashCode()要判斷二者地址是否相同。java中如果要判斷兩個對象是否相等,需要同時滿足地址 + 屬性都相同!
如果兩個對象相同(即:用 equals() 比較返回true),那么它們的 hashCode 值一定要相同; 如果兩個對象的 hashCode 相同,它們并不一定相同;舉例子:
只重寫 equals() 方法,不重寫 hashcode() 方法:
public class Student {private String name;private int age;public Student(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Student other = (Student) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}// 省略 get,set方法...}
執(zhí)行下面的程序看看效果:
public class hashTest {@Testpublic void test() {Student stu1 = new Student('Jimmy',24);Student stu2 = new Student('Jimmy',24);System.out.println('兩位同學(xué)是同一個人嗎?'+stu1.equals(stu2));System.out.println('stu1.hashCode() = '+stu1.hashCode());System.out.println('stu1.hashCode() = '+stu2.hashCode());}}
如果重寫了 equals() 而未重寫 hashcode() 方法,可能就會出現(xiàn)兩個沒有關(guān)系的對象 equals 相同(因為equals都是根據(jù)對象的特征進(jìn)行重寫的),但 hashcode 不相同的情況。因為此時 Student 類的 hashcode() 方法就是 Object 默認(rèn)的 hashcode()方 法,由于默認(rèn)的 hashcode()方法是根據(jù)對象的內(nèi)存地址經(jīng)哈希算法得來的,所以 stu1 != stu2,故兩者的 hashcode 值不一定相等。
根據(jù) hashcode 的規(guī)則,兩個對象相等其 hash 值一定要相等,矛盾就這樣產(chǎn)生了。上面我們已經(jīng)解釋了為什么要使用 hashcode 算法,所以即使字面量相等,但是產(chǎn)生兩個不同的 hashCode 值顯然不是我們想要的結(jié)果。
如果我們在重寫 equals() 時,也重寫了 hashCode() 方法:
public class Student {private String name;private int age;public Student(String name, int age) {super();this.name = name;this.age = age;}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Student other = (Student) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}// 省略 get,set方法...}
再來看執(zhí)行結(jié)果:
兩位同學(xué)是同一個人嗎?truestu1.hashCode() = 71578563stu1.hashCode() = 71578563
從 Student 類重寫后的 hashcode() 方法中可以看出,重寫后返回的新的 hash 值與 Student 的兩個屬性是有關(guān),這樣就確保了對象和對象地址之間的關(guān)聯(lián)性。
總結(jié)本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注好吧啦網(wǎng)的更多內(nèi)容!
相關(guān)文章:
