java map转string_【库学科技】32道常见的Java基础面试题
內(nèi)容來源于圖靈 侵刪。
什么是 Java 虛擬機(JVM)?為什么 Java 被稱作是“平臺無關(guān)的編程語言”?
Java 虛擬機是一個可以執(zhí)行 Java 字節(jié)碼的虛擬機進程。Java 源文件被編譯成能被 Java 虛擬機執(zhí)行的字節(jié)碼文件。
Java 被設(shè)計成允許應(yīng)用程序可以運行在任意的平臺,而不需要程序員為每一個平臺單獨重寫或者是重新編譯。Java 虛擬機讓這個變?yōu)榭赡?#xff0c;因為它知道底層硬件平臺的指令長度和其他特性。
JDK、JRE、JVM 分別是什么關(guān)系?
JDK 即為 Java 開發(fā)工具包,包含編寫 Java 程序所必須的編譯、運行等開發(fā)工具以及 JRE。開發(fā)工具如:用于編譯 Java 程序的 javac 命令、用于啟動 JVM 運行 Java 程序的 Java 命令、用于生成文檔的 Javadoc 命令以及用于打包的 jar 命令等等。
JRE 即為 Java 運行環(huán)境,提供了運行 Java 應(yīng)用程序所必須的軟件環(huán)境,包含有 Java 虛擬機(JVM)和豐富的系統(tǒng)類庫。系統(tǒng)類庫即為 Java 提前封裝好的功能類,只需拿來直接使用即可,可以大大的提高開發(fā)效率。
JVM 即為 Java 虛擬機,提供了字節(jié)碼文件(.class)的運行環(huán)境支持。 簡單說,就是 JDK 包含 JRE 包含 JVM。
Java 支持的數(shù)據(jù)類型有哪些?
Java 支持的數(shù)據(jù)類型包括基本數(shù)據(jù)類型和引用類型。基本數(shù)據(jù)類型如下。 整數(shù)值型:byte,short,int,long
字符型:char
浮點類型:float,double
布爾型:boolean
整數(shù)默認(rèn) int 型,小數(shù)默認(rèn)是 double 型。Float 和 long 類型的必須加后綴。比如 float f = 100f。
首先知道 String 是引用類型不是基本類型,引用類型聲明的變量是指該變量在內(nèi)存中實際存儲的是一個引用地址,實體在堆中。引用類型包括類、接口、數(shù)組等。String 類還是 final 修飾的。
什么是自動拆裝箱?
自動裝箱和拆箱就是基本類型和引用類型之間的轉(zhuǎn)換,至于為什么要轉(zhuǎn)換,因為基本類型轉(zhuǎn)換為引用類型后,就可以 new 對象,從而調(diào)用包裝類中封裝好的方法進行基本類型之間的轉(zhuǎn)換或者 toString(當(dāng)然用類名直接調(diào)用也可以,便于一眼看出該方法是靜態(tài)的),還有就是如果集合中想存放基本類型,泛型的限定類型只能是對應(yīng)的包裝類型。
什么是面向?qū)ο?#xff1f;
面向?qū)ο笫且环N思想,世間萬物都可以看做一個對象,這里只討論面向?qū)ο缶幊?OOP),Java 是一個支持并發(fā)、基于類和面向?qū)ο蟮挠嬎銠C編程語言,面向?qū)ο筌浖_發(fā)具有以下優(yōu)點:代碼開發(fā)模塊化,更易維護和修改;代碼復(fù)用性強;增強代碼的可靠性和靈活性;增加代碼的可讀性。
面向?qū)ο蟮乃拇蠡咎匦?#xff1f;
抽象:提取現(xiàn)實世界中某事物的關(guān)鍵特性,為該事物構(gòu)建模型的過程。對同一事物在不同的需求下,需要提取的特性可能不一樣。得到的抽象模型中一般包含:屬性(數(shù)據(jù))和操作(行為)。這個抽象模型我們稱之為類,對類進行實例化得到對象。
封裝:封裝可以使類具有獨立性和隔離性,保證類的高內(nèi)聚。只暴露給類外部或者子類必須的屬性和操作。類封裝的實現(xiàn)依賴類的修飾符(public、protected 和 private 等)。
繼承:對現(xiàn)有類的一種復(fù)用機制。一個類如果繼承現(xiàn)有的類,則這個類將擁有被繼承類的所有非私有特性(屬性和操作)。這里指的繼承包含:類的繼承和接口的實現(xiàn)。
多態(tài):多態(tài)是在繼承的基礎(chǔ)上實現(xiàn)的。多態(tài)的三個要素:繼承、重寫和父類引用指向子類對象。父類引用指向不同的子類對象時,調(diào)用相同的方法,呈現(xiàn)出不同的行為,就是類多態(tài)特性。多態(tài)可以分成編譯時多態(tài)和運行時多態(tài)。
抽象、封裝、繼承和多態(tài)是面向?qū)ο蟮幕A(chǔ)。
& 與 && 的區(qū)別?
& 運算符有兩種用法:(1) 按位與,(2) 邏輯與。&& 運算符是短路與運算。
邏輯與跟短路與的差別是非常巨大的,雖然二者都要求運算符左右兩端的布爾值都是 true 整個表達(dá)式的值才是 true。&& 之所以稱為短路運算是因為,如果 && 左邊的表達(dá)式的值是 false,右邊的表達(dá)式會被直接短路掉,不會進行運算。
很多時候我們可能都需要用 && 而不是 &,例如在驗證用戶登錄時判定用戶名不是 null 而且不是空字符串,應(yīng)當(dāng)寫為:
username != null && !username.equals(“”)
二者的順序不能交換,更不能用 & 運算符,因為第一個條件如果不成立,根本不能進行字符串的 equals 比較,否則會產(chǎn)生 NullPointerException 異常。
注意:邏輯或運算符(|)和短路或運算符(||)的差別也是如此。
什么是值傳遞和引用傳遞?
值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量。
引用傳遞一般是對于對象型變量而言的,傳遞的是該對象地址的一個副本,并不是原對象本身。一般認(rèn)為,Java 內(nèi)的傳遞都是值傳遞,Java 中實例對象的傳遞是引用傳遞。
是否可以在 static 環(huán)境中訪問非 static 變量?
static 變量在 Java 中是屬于類的,它在所有的實例中的值是一樣的。當(dāng)類被 Java 虛擬機載入的時候,會對 static 變量進行初始化。如果你的代碼嘗試不用實例來訪問非 static 的變量,編譯器會報錯,因為這些變量還沒有被創(chuàng)建出來,還沒有跟任何實例關(guān)聯(lián)上。
Java 中的方法覆蓋(Overriding)和方法重載(Overloading)是什么意思?
Java 中的方法重載發(fā)生在同一個類里面兩個或者是多個方法的方法名相同但是參數(shù)不同的情況。與此相對,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,參數(shù)列表和返回類型。覆蓋者可能不會限制它所覆蓋的方法的訪問。
Java 支持多繼承么?
Java 中類不支持多繼承,只支持單繼承(即一個類只有一個父類)。 但是 Java 中的接口支持多繼承,即一個子接口可以有多個父接口。(接口的作用是用來擴展對象的功能,一個子接口繼承多個父接口,說明子接口擴展了多個功能,當(dāng)類實現(xiàn)接口時,類就擴展了相應(yīng)的功能)。
Java 中,什么是構(gòu)造方法?什么是構(gòu)造方法重載?什么是復(fù)制構(gòu)造方法?
當(dāng)新對象被創(chuàng)建的時候,構(gòu)造方法會被調(diào)用。每一個類都有構(gòu)造方法。在程序員沒有給類提供構(gòu)造方法的情況下,Java 編譯器會為這個類創(chuàng)建一個默認(rèn)的構(gòu)造方法。
Java 中構(gòu)造方法重載和方法重載很相似。可以為一個類創(chuàng)建多個構(gòu)造方法。每一個構(gòu)造方法必須有它自己唯一的參數(shù)列表。
Java 不支持像 C++ 中那樣的復(fù)制構(gòu)造方法,這個不同點是因為如果你不自己寫構(gòu)造方法的情況下,Java 不會創(chuàng)建默認(rèn)的復(fù)制構(gòu)造方法。
接口和抽象類的區(qū)別是什么?
從設(shè)計層面來說,抽象是對類的抽象,是一種模板設(shè)計,接口是行為的抽象,是一種行為的規(guī)范。
Java 提供和支持創(chuàng)建抽象類和接口。它們的實現(xiàn)有共同點,不同點在于: 接口中所有的方法隱含的都是抽象的,而抽象類則可以同時包含抽象和非抽象的方法。
類可以實現(xiàn)很多個接口,但是只能繼承一個抽象類。類可以不實現(xiàn)抽象類和接口聲明的所有方法,當(dāng)然,在這種情況下,類也必須得聲明成是抽象的。
抽象類可以在不提供接口方法實現(xiàn)的情況下實現(xiàn)接口。 Java 接口中聲明的變量默認(rèn)都是 final 的。抽象類可以包含非 final 的變量。Java 接口中的成員函數(shù)默認(rèn)是 public 的。抽象類的成員函數(shù)可以是 private,protected 或者是 public。
接口是絕對抽象的,不可以被實例化。抽象類也不可以被實例化,但是,如果它包含 main 方法的話是可以被調(diào)用的。也可以參考 JDK8 中抽象類和接口的區(qū)別。
用最有效率的方法計算 2 乘以 8?
2 << 3(左移3位相當(dāng)于乘以2的3次方,右移3位相當(dāng)于除以2的3次方)。
手寫單例模式(餓漢和懶漢模式)和工廠模式?餓漢模式//餓漢式單例類.在類初始化時,已經(jīng)自行實例化public class Singleton1 {//私有的默認(rèn)構(gòu)造子private Singleton1() {}//已經(jīng)自行實例化private static final Singleton1 single = new Singleton1();//靜態(tài)工廠方法public static Singleton1 getInstance() {return single;}}?懶漢模式//懶漢式單例類.在第一次調(diào)用的時候?qū)嵗痯ublic class Singleton2 {//私有的默認(rèn)構(gòu)造子private Singleton2() {}//注意,這里沒有finalprivate static Singleton2 single=null;//靜態(tài)工廠方法public synchronized static Singleton2 getInstance() {if (single == null) {single = new Singleton2();}return single;}}?工廠模式,也可以參考之前的設(shè)計模式中的工廠模式,文末有鏈接。interface IFactory{public IProduct createProduct();}Class Factory implements IFactory{public IProduct createProduct(){return new Product();}}Public class client{Public Static void main (String [] args){IFactory factory=new Factory();IProduct product=factory.createProduct();product.ProductMethod();}}
String和StringBuilder、StringBuffer的區(qū)別?
Java 平臺提供了兩種類型的字符串:String 和 StringBuffer/StringBuilder,它們可以儲存和操作字符串。
其中 String 是只讀字符串,也就意味著 String 引用的字符串內(nèi)容是不能被改變的。
而 StringBuffer/StringBuilder 類表示的字符串對象可以直接進行修改。StringBuilder 是 Java 5 中引入的,它和 StringBuffer 的方法完全相同,區(qū)別在于它是在單線程環(huán)境下使用的,因為它的所有方面都沒有被 synchronized 修飾,因此它的效率也比 StringBuffer 要高。
Java 集合框架有哪些?說出一些集合框架的優(yōu)點?
每種編程語言中都有集合,最初的 Java 版本包含幾種集合類:Vector、Stack、HashTable 和 Array。隨著集合的廣泛使用,Java1.2 提出了囊括所有集合接口、實現(xiàn)和算法的集合框架。在保證線程安全的情況下使用泛型和并發(fā)集合類,Java 已經(jīng)經(jīng)歷了很久。它還包括在 Java 并發(fā)包中,阻塞接口以及它們的實現(xiàn)。集合框架的部分優(yōu)點如下: (1)使用核心集合類降低開發(fā)成本,而非實現(xiàn)我們自己的集合類。 (2)隨著使用經(jīng)過嚴(yán)格測試的集合框架類,代碼質(zhì)量會得到提高。 (3)通過使用 JDK 附帶的集合類,可以降低代碼維護成本。 (4)復(fù)用性和可操作性。
集合框架中的泛型有什么優(yōu)點?
Java1.5 引入了泛型,所有的集合接口和實現(xiàn)都大量地使用它。泛型允許我們?yōu)榧咸峁┮粋€可以容納的對象類型。因此,如果你添加其它類型的任何元素,它會在編譯時報錯。這避免了在運行時出現(xiàn) ClassCastException,因為你將會在編譯時得到報錯信息。泛型也使得代碼整潔,我們不需要使用顯式轉(zhuǎn)換和 instanceOf 操作符。它也給運行時帶來好處,因為不會產(chǎn)生類型檢查的字節(jié)碼指令。
Java 集合框架的基礎(chǔ)接口有哪些?
Collection 為集合層級的根接口。一個集合代表一組對象,這些對象即為它的元素。Java 平臺不提供這個接口任何直接的實現(xiàn)。
Set 是一個不能包含重復(fù)元素的集合。這個接口對數(shù)學(xué)集合抽象進行建模,被用來代表集合,就如一副牌。
List 是一個有序集合,可以包含重復(fù)元素。你可以通過它的索引來訪問任何元素。List 更像長度動態(tài)變換的數(shù)組。
Map 是一個將 key 映射到 value 的對象。一個 Map 不能包含重復(fù)的 key,每個 key 最多只能映射一個 value。
一些其它的接口有 Queue、Dequeue、SortedSet、SortedMap 和 ListIterator。
為何 Collection 不從 Cloneable 和 Serializable 接口繼承?
Collection 接口指定一組對象,對象即為它的元素。如何維護這些元素由 Collection 的具體實現(xiàn)決定。例如,一些如 List 的 Collection 實現(xiàn)允許重復(fù)的元素,而其它的如 Set 就不允許。很多 Collection 實現(xiàn)有一個公有的 clone 方法。然而,把它放到集合的所有實現(xiàn)中也是沒有意義的。這是因為 Collection 是一個抽象表現(xiàn),重要的是實現(xiàn)。
當(dāng)與具體實現(xiàn)打交道的時候,克隆或序列化的語義和含義才發(fā)揮作用。所以,具體實現(xiàn)應(yīng)該決定如何對它進行克隆或序列化,或它是否可以被克隆或序列化。在所有的實現(xiàn)中授權(quán)克隆和序列化,最終導(dǎo)致更少的靈活性和更多的限制,特定的實現(xiàn)應(yīng)該決定它是否可以被克隆和序列化。
為何 Map 接口不繼承 Collection 接口?
盡管 Map 接口和它的實現(xiàn)也是集合框架的一部分,但 Map 不是集合,集合也不是 Map。因此,Map 繼承 Collection 毫無意義,反之亦然。
如果 Map 繼承 Collection 接口,那么元素去哪兒?Map 包含key-value 對,它提供抽取 key 或 value 列表集合的方法,但是它不適合“一組對象”規(guī)范。
什么是迭代器(Iterator)?
Iterator 接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素,但是不可以直接調(diào)用集合的 remove(Object Obj) 刪除,可以通過迭代器的 remove() 方法刪除。
Iterator 和 ListIterator 的區(qū)別是什么?
Iterator 可用來遍歷 Set 和 List 集合,但是 ListIterator 只能用來遍歷 List。
Iterator 對集合只能是前向遍歷,ListIterator 既可以前向也可以后向。
ListIterator 實現(xiàn)了 Iterator 接口,并包含其他的功能。比如:增加元素,替換元素,獲取前一個和后一個元素的索引等等。
Java 中的 HashMap 的工作原理是什么?
我們知道在 Java 中最常用的兩種結(jié)構(gòu)是數(shù)組和模擬指針(引用),幾乎所有的數(shù)據(jù)結(jié)構(gòu)都可以利用這兩種來組合實現(xiàn),HashMap 也是如此。實際上 HashMap 是一個“鏈表散列”。
HashMap 是基于 hashing 的原理,我們使用 put(key, value) 存儲對象到 HashMap 中,使用 get(key) 從 HashMap 中獲取對象。當(dāng)我們給 put() 方法傳遞鍵和值時,我們先對鍵調(diào)用 hashCode() 方法,返回的 hashCode 用于找到 bucket 位置來儲存 Entry 對象。
當(dāng)兩個對象的 hashcode 相同會發(fā)生什么?
因為 hashcode 相同,所以它們的 bucket 位置相同,“碰撞”會發(fā)生。因為 HashMap 使用鏈表存儲對象,這個 Entry(包含有鍵值對的 Map.Entry 對象)會存儲在鏈表中。
如果兩個鍵的 hashcode 相同,你如何獲取值對象?
當(dāng)我們調(diào)用 get() 方法,HashMap 會使用鍵對象的 hashcode 找到 bucket 位置,然后會調(diào)用 keys.equals() 方法去找到鏈表中正確的節(jié)點,最終找到要找的值對象。
hashCode() 和 equals() 方法有何重要性?
HashMap 使用 Key 對象的 hashCode() 和 equals() 方法去決定 key-value 對的索引。當(dāng)我們試著從 HashMap 中獲取值的時候,這些方法也會被用到。
如果這些方法沒有被正確地實現(xiàn),在這種情況下,兩個不同 Key 也許會產(chǎn)生相同的 hashCode() 和 equals() 輸出,HashMap 將會認(rèn)為它們是相同的,然后覆蓋它們,而非把它們存儲到不同的地方。
同樣的,所有不允許存儲重復(fù)數(shù)據(jù)的集合類都使用 hashCode() 和 equals() 去查找重復(fù),所以正確實現(xiàn)它們非常重要。equals() 和 hashCode() 的實現(xiàn)應(yīng)該遵循以下規(guī)則:
如果 o1.equals(o2),那么o1.hashCode() == o2.hashCode()總是為true的。 如果 o1.hashCode() == o2.hashCode(),并不意味著o1.equals(o2)會為true。
HashMap 和 HashTable 有什么區(qū)別?
一般現(xiàn)在不建議用 HashTable,一是 HashTable 是遺留類,內(nèi)部實現(xiàn)很多沒優(yōu)化和冗余。二是即使在多線程環(huán)境下,現(xiàn)在也有同步的 ConcurrentHashMap 替代,沒有必要因為是多線程而用 HashTable。
HashMap 是非線程安全的,HashTable 是線程安全的。
HashMap 的鍵和值都允許有 null 值存在,而 HashTable 則不行。
因為線程安全的問題,HashMap 效率比 HashTable 的要高。
HashTable 是同步的,而 HashMap 不是。因此,HashMap 更適合于單線程環(huán)境,而 HashTable 適合于多線程環(huán)境。
如何決定選用 HashMap 還是 TreeMap?
對于在 Map 中插入、刪除和定位元素這類操作,HashMap 是最好的選擇。然而,假如你需要對一個有序的 key 集合進行遍歷, TreeMap 是更好的選擇。基于你的 collection 的大小,也許向 HashMap 中添加元素會更快,將 map 換為 TreeMap 進行有序 key 的遍歷。
ArrayList 和 Vector 有何異同點?
ArrayList 和 Vector 在很多時候都很類似。
(1)兩者都是基于索引的,內(nèi)部由一個數(shù)組支持。
(2)兩者維護插入的順序,我們可以根據(jù)插入順序來獲取元素。
(3)ArrayList 和 Vector 的迭代器實現(xiàn)都是 fail-fast 的。
(4)ArrayList 和 Vector 兩者允許 null 值,也可以使用索引值對元素進行隨機訪問。以下是ArrayList和Vector的不同點。
(1)Vector 是同步的,而 ArrayList 不是。然而,如果你尋求在迭代的時候?qū)α斜磉M行改變,你應(yīng)該使用 CopyOnWriteArrayList。
(2)ArrayList 比 Vector 快,它因為有同步,不會過載。
(3)ArrayList 更加通用,因為我們可以使用 Collections 工具類輕易地獲取同步列表和只讀列表。
Array 和 ArrayList 有何區(qū)別?什么時候更適合用 Array?
Array 可以容納基本類型和對象,而 ArrayList 只能容納對象。 Array 是指定大小的,而 ArrayList 大小是固定的。Array 沒有提供 ArrayList 那么多功能,比如 addAll、removeAll 和 iterator 等。盡管 ArrayList 明顯是更好的選擇,但也有些時候 Array 比較好用,比如下面的三種情況。
(1)如果列表的大小已經(jīng)指定,大部分情況下是存儲和遍歷它們。
(2)對于遍歷基本數(shù)據(jù)類型,盡管 Collections 使用自動裝箱來減輕編碼任務(wù),在指定大小的基本類型的列表上工作也會變得很慢。
(3)如果你要使用多維數(shù)組,使用 [][] 比 List。
快速失敗(fail-fast)和安全失敗(fail-safe)的區(qū)別是什么?
快速失敗:當(dāng)你在迭代一個集合的時候,如果有另一個線程正在修改你正在訪問的那個集合時,就會拋出一個 ConcurrentModification 異常。 在 java.util 包下的都是快速失敗。
安全失敗:你在迭代的時候會去底層集合做一個拷貝,所以你在修改上層集合的時候是不會受影響的,不會拋出 ConcurrentModification 異常。在java.util.concurrent 包下的全是安全失敗的。
總結(jié)
以上是生活随笔為你收集整理的java map转string_【库学科技】32道常见的Java基础面试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 方正计算机软件保护进超级用户,超级用户权
- 下一篇: python使用pkg包_Python