整理的java面試題目及相關答案,僅供參考


1.操作系統中 heap stack 的區別

Heap堆和Satck棧是數據結構的兩種,堆主要用來存放對象的,棧主要是用來執行程序的堆是隊列優先,先進先出,棧是先進后出;

棧用來存儲臨時變量,自動變量,保護現場,CPU會有一個寄存器叫做SP,棧指針,CPU通用寄存器是有限的,不能將每個操作數都放在寄存器中,那暫時不用的就要放到棧內存,叫入棧,要用時在出棧,計算機經常會正在干一件事,忽然有了另一件事,那前一件事的數據就不能繼續留在CPU中,做法就是入棧到內存保護現場,等另一件事昨晚了,在將原來數據返回CPU繼續做;

堆是預先申請一片內存,可能用到可能用不到,他的生存周期取決於編程者,以申請新的,也可以隨時扔掉它,編程者使用到的主要的數據都在這里;

2.什么是基於注解的切面實現:

aspect中的注解實現就是用注解定義切面,切點,一般用在實物和日志記錄中;

3.什么是 對象/關系 映射集成模塊:

對象關系映射(Object Relational Mapping,簡稱ORM)是通過使用描述對象和數據庫之間映射的元數據,將面向對象語言程序中的對象自動持久化到關系數據庫中。本質上就是將數據從一種形式轉換到另外一種形式。Spring通過提供ORM模塊在JDBC的基礎上支持對象關系映射工具。這樣的支持使得Spring可以集成主流的ORM框架,包括Hibernate

  1. 什么是 Java 的反射機制:

是指程序可以訪問,檢測和修改它本身狀態或行為的一種能力,通過反射機制訪問java對象的屬性,方法,構造方法等

優缺點:

 

優點:

1、反射提高了程序的靈活性和擴展性。

2、降低耦合性,提高自適應能力。

3、它允許程序創建和控制任何類的對象,無需提前硬編碼目標類。

 

缺點:

1、性能問題:使用反射基本上是一種解釋操作,用於字段和方法接入時要遠慢於直接代碼。因此反射機制主要應用在對靈活性和拓展性要求很高的系統框架上,普通程序不建議使用。

  

2、使用反射會模糊程序內部邏輯;程序員希望在源代碼中看到程序的邏輯,反射卻繞過了源代碼的技術,因而會帶來維護的問題,反射代碼比相應的直接代碼更復雜。

5什么是 ACID

ACID,指數據庫事務正確執行的四個基本要素的縮寫。包含:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。一個支持事務(Transaction)的數據庫,必須要具有這四種特性,否則在事務過程(Transaction processing)當中無法保證數據的正確性,交易過程極可能達不到交易方的要求

--原子性(Atomic):事務中各項操作,要么全做要么全不做,任何一項操作的失敗都會導致整個事務的失敗;

- 一致性(Consistent):事務結束后系統狀態是一致的;

- 隔離性(Isolated):並發執行的事務彼此無法看到對方的中間狀態;

- 持久性(Durable):事務完成后所做的改動都會被持久化,即使發生災難性的失敗。通過日志和同步備份可以在故障發生后重建數據.

6.BSCS的聯系與區別:

B/S模式是指在TCP/IP的支持下,以HTTP為傳輸協議,客戶端通過Browser訪問Web服務器以及與之相連的后台數據庫的技術及體系結構。它由瀏覽器、Web服務器、應用服務器和數據庫服務器組成。客戶端的瀏覽器通過URL訪問Web服務器,Web服務器請求數據庫服務器,並將獲得的結果以HTML形式返回客戶端瀏覽器。

c/s在系統機構上和B/S相似,不過需要在客戶端安裝一個客戶端軟件,由這個軟件對服務器的數據進行讀寫,就像我們常用的qq,就是這種模式

  1. Cookie Session的區別:

Cookie數據存放在客戶端,服務器知道其中的數據;Session數據存放在服務器,客戶端不知道其中的數據;

Session存放對象,cookie存放字符串;

Cookie不安全,別人可以分析存放在cookie進行cookie欺騙;

Session會在一段時間內保存到服務器中,但是當訪問量比較多時,比較占用資源;

單個cookie保存的數據一般不超過4k,一般瀏覽器限制最多保存20cookie

  1. fail-fast fail-safe 機制有什么區別:

java.util包下面的所有的集合類都是快速失敗的,而java.util.concurrent包下面的所有的類都是安全失敗的。

fail-fast機制在遍歷一個集合時,當集合結構被修改,會拋出Concurrent Modification Exception

fail-fast會在以下兩種情況下拋出ConcurrentModificationException

1)單線程環境

集合被創建后,在遍歷它的過程中修改了結構。

注意 remove()方法會讓expectModcountmodcount 相等,所以是不會拋出這個異常。

2)多線程環境

當一個線程在遍歷這個集合,而另一個線程對這個集合的結構進行了修改。

fail-safe任何對集合結構的修改都會在一個復制的集合上進行修改,因此不會拋出ConcurrentModificationException

fail-safe機制有兩個問題

1)需要復制集合,產生大量的無效對象,開銷大

2)無法保證讀取的數據是目前原始數據結構中的數據。

9.get post請求的區別

GET方式:

1GET方式是以實體的方式得到由請求URL所指定資源的信息,如果請求URL只是一個數據產生過程,那么最終要在響應實體中返回的是處理過程的結果所指向的資源,而不是處理過程的描述。也就是說,GET的到的信息是資源,而不是資源的處理過程。

2、請的求的數據會附加在URL之后,以?分隔URL和傳輸數據,多個參數用&連接。URL編碼格式采用的是ASCII編碼,而不是Unicode,即所有的非ASCII字符都要編碼之后再傳輸。

3、因為URL的長度限制,GET方式傳輸的數據大小有所限制,傳送的數據量不超過2KB

4GET方式服務器端用Request.QueryString獲取變量的值。

5GET方式傳輸的參數安全性低,因為傳輸的數據會顯示在請求的URL中。

POST方式:

1、用來向目的服務器發出請求,要求它接收被附在請求后的實體,並把它當做請求隊列中請求URL所指定資源的附加新子項。

 

2POST方式將表單內各個字段和內容放置在HTML HEADER中一起傳送到Action屬性所指定的URL地址,用戶是看不到這個過程的。

3POST方式傳送的數據量比較大,一般被默認為沒有限制,但是根據IIS的配置,傳輸量也是不同的。

4POST方式在服務器端用Request.Form獲取提交的數據。

5POST方式傳輸的數據安全性較高,因為數據傳輸不是明顯顯示的。

10.Interface abstract 類的區別:

1.abstarct

  • 類中可以出現abstract方法,也可以就包含普通方法。(也就是說一旦出現了抽象方法,那這個類必定是抽象類)
  • 不能創建實例對象,就是不能使用new運算符創建類的對象。
  • abstract類的對象可以成為子類對象的上轉型對象,可以調用子類重寫的方法。
  • abstract類是可以不用有abstract方法的。
  • 若一個抽象類是另一個抽象類的子類,那么它可以重寫父類的抽象類,也可以直接繼承。

2 interface

  • 接口體中包含常量的聲明(無變量)和抽象方法2部分。
  • 只有抽象方法,沒有普通方法。
  • 常量的訪問權限都是public的,而且都是static常量(允許省略public,final,static修飾符)
  • 所有抽象方法的訪問權限一定都是public的(允許省略public,static修飾符)。
  • 當一個普通類實現了一個接口時,那么必須重寫這個接口中的所有方法,而且訪問權限只能是
  • public.
  • 接口也有實現權限之分。
  • implements聲明實現這個接口。若父類實現了某個接口,那么子類也就自然實現了該接口,子類也不必再顯示地使用關鍵
  • 接口可以被繼承,可以通過關鍵字extends聲明一個接口是另一個接口的子接口。由於接口的方法和常量都是public的,子接口講繼父接口的全部方法和常量。
  1. IOC的優點是什么:

IOC(Inversion of Control)控制反轉,將控制權(創建對象和對象之間的依賴關系的權利)交給

spring容器;

IOC模式將耦合代碼從程序中移出,放到統一的XML文件中管理。

IOC容器通過配置文件來管理對象的生命周期、依賴關系等,這樣就不用重新修改並編譯具體的代碼,從而實現組件之間的解耦

IOC的優點:實現組件之間的解耦,提高程序的靈活性和可維護性。

  1. IO NIO的區別,NIO優點:

IO是面向流的,NIO是面向緩沖區的

Java IO的各種流是阻塞的,這意味着,當一個線程調用read() write()時,該線程被阻塞,直到有一些數據被讀取,或數據完全寫入。該線程在此期間不能再干任何事情了。

Java NIO的非阻塞模式,,使一個線程從某通道發送請求讀取數據,但是它僅能得到目前可用的數據,如果目前沒有數據可用時,就什么都不會獲取,而不是保持線程阻塞,所以直至數據變的可以讀取之前,該線程可以繼續做其他的事情。 非阻塞寫也是如此。一個線程請求寫入一些數據到某通道,但不需要等待它完全寫入,這個線程同時可以去做別的事情。 線程通常將非阻塞IO的空閑時間用於在其它通道上執行IO操作,所以一個單獨的線程現在可以管理多個輸入和輸出通道(channel

 Java NIO的選擇器允許一個單獨的線程來監視多個輸入通道

13.Java 8 / Java 7 為我們提供了什么新功能:

1.jdk7語法上:

1.1二進制變量的表示,支持將整數類型用二進制來表示,用0b開頭。

1.2  Switch語句支持string類型

3.1.可以使用try-with-resources自動關閉Connection, ResultSet, 和 Statement資源對象

14.什么是競態條件? 舉個例子說明。

當兩個線程競爭同一資源時,如果對資源的訪問順序敏感,就稱存在競態條件。

導致競態條件發生的代碼區稱作臨界區。

 

在臨界區中使用適當的同步就可以避免競態條件。

臨界區實現方法有兩種,一種是用synchronized,一種是用Lock顯式鎖實現。

class Counter {

    protected long count = 0;

    public void add(long value) {

        this.count = this.count + value;

    }

}

 觀察線程A和B交錯執行會發生什么,兩個線程分別加了2和3到count變量上,兩個線程執行結束后count變量的值應該等於5。然而由於兩個線程是交叉執行的,兩個線程從內存中讀出的初始值都是0。然后各自加了2和3,並分別寫回內存。最終的值並不是期望的5,而是最后寫回內存的那個線程的值,上面例子中最后寫回內存的是線程A,但實際中也可能是線程B。如果沒有采用合適的同步機制,線程間的交叉執行情況就無法預料。

add()方法就是一個臨界區,它會產生競態條件。

  1. JRE、JDK、JVM 及 JIT 之間有什么不同

java虛擬機(JVM)

    使用java編程語言的主要優勢就是平台的獨立性。你曾經想知道過java怎么實現平台的獨立性嗎?對,就是虛擬機,它抽象化了硬件設備,開發者和他們的程序的得以操作系統。虛擬機的職責就是處理和操作系統的交流。java不同的接口規范對任何平台都有良好的支持,因為jvm很好的實現了每個平台的規范。jvm可以理解偽代碼字節碼,在用戶和操作系統之間建立了一層樞紐。

 

java運行時環境(JRE)

    java運行時環境是JVM的一個超集。JVM對於一個平台或者操作系統是明確的,而JRE確實一個一般的概念,他代表了完整的運行時環境。我們在jre文件夾中看到的所有的jar文件和可執行文件都會變成運行時的一部分。事實上,運行時JRE變成了JVM。所以對於一般情況時候使用JRE,對於明確的操作系統來說使用JVM。當你下載了JRE的時候,也就自動下載了JVM。

 

java開發工具箱(JDK)

    java開發工具箱指的是編寫一個java應用所需要的所有jar文件和可執行文件。事實上,JRE是JDK的一部分。如果你下載了JDK,你會看到一個名叫JRE的文件夾在里面。JDK中要被牢記的jar文件就是tools.jar,它包含了用於執行java文檔的類還有用於類簽名的jar包。

 

即時編譯器(JIT)

即時編譯器是種特殊的編譯器,它通過有效的把字節碼變成機器碼來提高JVM的效率。JIT這種功效很特殊,因為他把檢測到的相似的字節碼編譯成單一運行的機器碼,從而節省了CPU的使用。這和其他的字節碼編譯器不同,因為他是運行時(第一類執行的編譯?)the firs of its kind to perform the compilation(從字節碼到機器碼)而不是在程序運行之前。正是因為這些,動態編譯這個詞匯才和JIT有那么緊密的關系

  1. MVC的各個部分都有那些技術來實現?如何實現?

MVC 是 Model-View-Controller 的簡寫。 Model 代表的是應用的業務邏輯( 通過

JavaBean, EJB 組件實現), View 是應用的表示面( 由 JSP 頁面產生), Controller 是提供應用的處理過程控制( 一般是一個 Servlet), 通過這種設計模型把應用邏輯, 處理過程和顯示邏輯分成不同的組件實現。 這些組件可以進行交互和重用。

  1. RPC 通信和 RMI 區別

1. RPC 不支持對象, 采用http協議

2. RMI支持傳輸對象。采用tcp/ip 協議

3. RMI只限於JAVA語言,RPC跨語言

18.什么是 Web Service(Web服務):

WebService是一種跨編程語言和跨操作系統平台的遠程調用技術。

謂跨編程語言和跨操作平台,就是說服務端程序采用java編寫,客戶端程序則可以采用其他編程語言編寫,反之亦然!跨操作系統平台則是指服務端程序和客戶端程序可以在不同的操作系統上運行。

所謂遠程調用,就是一台計算機a上的一個程序可以調用到另外一台計算機b上的一個對象的方法,譬如,銀聯提供給商場的pos刷卡系統,商場的POS機轉賬調用的轉賬方法的代碼其實是跑在銀行服務器上。再比如,amazon,天氣預報系統,淘寶網,校內網,百度等把自己的系統服務以webservice服務的形式暴露出來,讓第三方網站和程序可以調用這些服務功能,這樣擴展了自己系統的市場占有率,往大的概念上吹,就是所謂的SOA應用。

19.WEB容器主要有哪些功能? 並請列出一些常見的WEB容器名字。.

Web容器給處於其中的應用程序組件(JSP,SERVLET)提供一個環境,使JSP,SERVLET直接跟容器中的環境變量交互,不必關注其它系統問題。主要有WEB服務器來實現。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。  

常見的有容器  Apache, IIS, Tomcat, Resin 等等

  1. 一個”.java”源文件中是否可以包含多個類(不是內部類)?有什么限制

這個是可以的,一個“.java”源文件里面可以包含多個類,但是只允許有一個public類,並且類名必須和文件名一致。

每個編譯單元只能有一個public 類。這么做的意思是,每個編譯單元只能有一個公開的接口,而這個接口就由其public 類來表示。

你可以根據需要,往這個文件里面添加任意多個提供輔助功能的package 權限的類。但是如果這個編譯單元里面有兩個或兩個以上的public 類的話,程序就不知道從哪里導入了,編譯器就會報錯。

  1. 簡單說說你了解的類加載器。是否實現過類加載器

虛擬機設計團隊把類加載階段中“通過一個類的全限定名來獲取描述此類的二進制字節流”這個動作放到Java虛擬機外部去實現,以便讓應用程序自己決定如何去獲取所需要的類。實現這個動作的模塊稱為“類加載器”。

  1. 解釋一下什么叫AOP(面向切面編程)

在運行時,動態地將代碼切入到類的指定方法、指定位置上的編程思想就是面向切面的編程。

  1. 請簡述 Servlet 的生命周期及其相關的方法

Servlet 生命周期:Servlet 加載--->實例化--->服務--->銷毀。

init():在Servlet的生命周期中,僅執行一次init()方法。它是在服務器裝入Servlet時執行的,負責初始化Servlet對象。可以配置服務器,以在啟動服務器或客戶機首次訪問Servlet時裝入Servlet。無論有多少客戶機訪問Servlet,都不會重復執行init()。

service():它是Servlet的核心,負責響應客戶的請求。每當一個客戶請求一個HttpServlet對象,該對象的Service()方法就要調用,而且傳遞給這個方法一個“請求”(ServletRequest)對象和一個“響應”(ServletResponse)對象作為參數。在HttpServlet中已存在Service()方法。默認的服務功能是調用與HTTP請求的方法相應的do功能。

destroy(): 僅執行一次,在服務器端停止且卸載Servlet時執行該方法。當Servlet對象退出生命周期時,負責釋放占用的資源。一個Servlet在運行service()方法時可能會產生其他的線程,因此需要確認在調用destroy()方法時,這些線程已經終止或完成。

  1. 請簡述一下 Ajax 的原理及實現步驟

Ajax的原理簡單來說通過XmlHttpRequest對象來向服務器發異步請求,從服務器獲得數據,然后用javascript來操作DOM而更新頁面。

1、創建XMLHttpRequest對象(需要考慮各瀏覽器兼容的問題)

2、使用XMLHttpRequest對象打開一個連接(指定連接方式<post/get>和連接地址以及是否同步);調用XMLHttpRequest對象的open方法。第一個參數是提交數據的方式,取值為post/get;第二個參數是提交的目標頁面(也就是用於處理提交數據的頁面);第三個參數指定是否請求是異步的-缺省值為true,為了發送一個同步請求,需要把這個參數設置為false。

3、設置請求的頭部(請求的類型和請求的編碼格式)

4、設置回調函數

主要用於處理從服務端發送給客戶端的數據,主要使用javascript去調用頁面中的元素,並根據服務端返回的結果去控制頁面中元素的更新。內部實現實際上是javascript中的事件處理機制。

5、發送請求:調用XMLHttpRequest對象的send方法實現數據的發送。

6、更新頁面顯示

25.簡單描述Struts的主要功能

鏈接:https://www.cnblogs.com/god-1949-keshi/p/7124277.html

struts2的目的就是把請求和顯示的結果分開,而不是單純的運行一個jsp頁面

攔截器可以說相當於是個過濾器:就是把 不想要的或不想顯示的內容給過濾掉。攔截器可以抽象出一部分代碼可以用來完善原來的action。同時可以減輕代碼冗余,提高重用率。

比如在登入一個頁面時,如果要求用戶密碼、權限等的驗證,就可以用自定義的攔截器進行密碼驗證和權限限制。對符合的登入者才跳轉到正確頁面。這樣如果有新增權限的話,不用在action里修改任何代碼,直接在interceptor里修改就行了

26.什么是Java虛擬機?為什么Java被稱作是“平台無關的編程語言”

一、什么是java虛擬機?

java虛擬機是執行字節碼文件(.class)的虛擬機進程。

java源程序(.java)被編譯器編譯成字節碼文件(.class)。然后字節碼文件,將由java虛擬機,解釋成機器碼(不同平台的機器碼不同)。利用機器碼操作硬件和操作系統

 

二、為什么java被稱為平台無關的編程語言?

因為不同的平台裝有不同的JVM,它們能夠將相同的.class文件,解釋成不同平台所需要的機器碼。正是因為有JVM的存在,java被稱為平台無關的編程語言

  1. 什么是正則表達式?用途是什么?哪個包使用正則表達式來實現模式匹配

簡單的說就是,用一小段簡單的各種字符的組合,即叫做 正則表達式,去實現復雜的:

字符串匹配,查找你到你所需要的內容,以便后期提取出來你所要的內容;

java.util.regex

  1. 什么是懶加載(Lazy Loading)

懶加載就是什么時候使用什么時候開辟空間,不用的時候只是一個指針不占用內存,當使用的時候為其alloc/init,這時候才占用內存.只要不使用就永遠不會真正生成,不會占用空間.

29什么是尾遞歸,為什么需要尾遞歸

尾遞歸是指所有遞歸形式的調用,一定是發生在函數的末尾。形式上只要最后一個return語句是單純函數就可以。

尾遞歸和一般的遞歸不同在對內存的占用,普通遞歸創建stack累積而后計算收縮,尾遞歸只會占用恆量的內存(和迭代一樣)

30.什么是控制反轉(Inversion of Control)與依賴注入(Dependency Injection

IoCInversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來說,就是由spring來負責控制對象的生命周期和對象間的關系。

這是什么意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪里有長得漂亮身材又好的mm,然后打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然后嘿嘿……這個過程是復雜深奧的,我們必須自己設計和面對每個環節。傳統的程序開發也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之后還要將對象銷毀(比如Connection等),對象始終會和其他的接口或類藕合起來。

那么IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什么樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周傑倫,速度像卡洛斯,技術像齊達內之類的,然后婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明了,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。

 

關鍵字

 

finalize

 

什么是finalize()方法

finalize()方法什么時候被調用

答:finalize()Objectprotected方法,子類可以覆蓋該方法以實現資源清理工作,GC在回收對象之前調用該方法。

主要的用途是回收特殊渠道申請的內存。Java程序有垃圾回收器,所以一般情況下內存問題不用程序員操心。但有一種JNI(Java Native Interface)調用non-Java程序(CC++),finalize()的工作就是回收這部分的內存。

 

final finalize 的區別

final關鍵字有哪些用法

final, finally, finalize的區別

finalfinalize finally 的不同之處?

一個類被聲明為final類型,表示了什么意思

 

答:

Final

final關鍵字可以用於類,方法,變量前,用來表示該關鍵字修飾的類,方法,變量具有不可變的特性。

1final關鍵字用於基本數據類型前:這時表明該關鍵字修飾的變量是一個常量,在定義后該變量的值就不能被修改。

2final關鍵字用於方法聲明前:這時意味着該方法時最終方法,只能被調用,不能被覆蓋,但是可以被重載。

3final關鍵字用於類名前:此時該類被稱為最終類,該類不能被其他類繼承。

Finalize

finalize方法來自於java.lang.Object,用於回收資源。

可以為任何一個類添加finalize方法。finalize方法將在垃圾回收器清除對象之前調用。

在實際應用中,不要依賴使用該方法回收任何短缺的資源,這是因為很難知道這個方法什么時候被調用。

Finally

當代碼拋出一個異常時,就會終止方法中剩余代碼的處理,並退出這個方法的執行。假如我們打開了一個文件,但在處理文件過程中發生異常,這時文件還沒有被關閉,此時就會產生資源回收問題。對此,java提供了一種好的解決方案,那就是finally子句,finally子句中的語句是一定會被執行的,所以我們只要把前面說的文件關閉的語句放在finally子句中無論在讀寫文件中是否遇到異常退出,文件關閉語句都會執行,保證了資源的合理回收。

 

 

final static 關鍵字可以用於哪里?它們的作用是什么

1static方法

  static方法一般稱作靜態方法,由於靜態方法不依賴於任何對象就可以進行訪問,因此對於靜態方法來說,是沒有this的,因為它不依附於任何對象,既然都沒有對象,就談不上this了。並且由於這個特性,在靜態方法中不能訪問類的非靜態成員變量和非靜態成員方法,因為非靜態成員方法/變量都是必須依賴具體的對象才能夠被調用。

2static變量

  static變量也稱作靜態變量,靜態變量和非靜態變量的區別是:靜態變量被所有的對象所共享,在內存中只有一個副本,它當且僅當在類初次加載時會被初始化。而非靜態變量是對象所擁有的,在創建對象的時候被初始化,存在多個副本,各個對象擁有的副本互不影響。

  static成員變量的初始化順序按照定義的順序進行初始化。

3static代碼塊

  static關鍵字還有一個比較關鍵的作用就是 用來形成靜態代碼塊以優化程序性能。static塊可以置於類中的任何地方,類中可以有多個static塊。在類初次被加載的時候,會按照static塊的順序來執行每個static塊,並且只會執行一次

 

能否在運行時向 static final 類型的賦值

答:final static 變量就只能在定義的時候就初始化,否則既無法在構造方法中初始化,系統又不會賦默認值,相當於這個變量被定義出來是毫無用處的。  因此javafinal static變量必須初始化。

 

使用final關鍵字修飾一個變量時,是引用不能變,還是引用的對象不能變

答:使用final關鍵字修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容還是可以改變的。

throws, throw, try, catch, finally分別代表什么意義

答:throws是獲取異常

throw是拋出異常

try是將會發生異常的語句括起來,從而進行異常的處理,

catch是如果有異常就會執行他里面的語句,

finally不論是否有異常都會進行執行的語句。

throws是用來聲明一個方法可能拋出的所有異常信息,而throw則是指拋出的一個具體的異常類型。此外throws是將異常聲明但是不處理,而是將異常往上傳,誰調用我就交給誰處理;

1throws出現在方法函數頭;而throw出現在函數體。

2throws表示出現異常的一種可能性,並不一定會發生這些異常;throw則是拋出了異常,執行throw則一定拋出了某種異常。

3、兩者都是消極處理異常的方式(這里的消極並不是說這種方式不好),只是拋出或者可能拋出異常,但是不會由函數去處理異常,真正的處理異常由函數的上層調用處理。

Java 有幾種修飾符?分別用來修飾什么

答:

方法的修飾符有兩類:

1.訪問控制修飾符(public,private,protected,package)

2.方法本身修飾符(static,final,abstract,native,synchronized)

類的修飾符:

1.前綴修飾符(public,abstract,final)

2.后綴修飾符(extends,implements)

 

 

volatile

 

volatile 修飾符的有過什么實踐

答:

一種實踐是用 volatile 修飾 long double 變量,使其能按原子類型來讀寫。double long 都是64位寬,因此對這兩種類型的讀是分為兩部分的,第一次讀取第一個 32 位,然后再讀剩下的 32 位,這個過程不是原子的,但 Java volatile 型的 long double 變量的讀寫是原子的。volatile 修復符的另一個作用是提供內存屏障(memory barrier),例如在分布式框架中的應用。簡單的說,就是當你寫一個 volatile 變量之前,Java 內存模型會插入一個寫屏障(write barrier),讀一個 volatile 變量之前,會插入一個讀屏障(read barrier)。意思就是說,在你寫一個 volatile 域時,能保證任何線程都能看到你寫的值,同時,在寫之前,也能保證任何數值的更新對所有線程是可見的,因為內存屏障會將其他所有寫的值更新到緩存。

volatile 變量是什么?volatile 變量和 atomic 變量有什么不同

答:volatile就是告訴程序,該變量是易變的,不穩定的,每次必須去主存讀取,而不要從自己的緩存中獲取副本

volatile 類型變量提供什么保證?能使得一個非原子操作變成原子操作嗎

答:一個典型的例子是在類中有一個 long 類型的成員變量。如果你知道該成員變量會被多個線程訪問,如計數器、價格等,你最好是將其設置為 volatile。為什么?因為 Java 中讀取 long 類型變量不是原子的,需要分成兩步,如果一個線程正在修改該 long 變量的值,另一個線程可能只能看到該值的一半(前 32 位)。但是對一個 volatile 型的 long double 變量的讀寫是原子。

能創建 volatile 數組嗎?

答:能,Java 中可以創建 volatile 類型數組,不過只是一個指向數組的引用,而不是整個數組。我的意思是,如果改變引用指向的數組,將會受到 volatile 的保護,但是如果多個線程同時改變數組的元素,volatile 標示符就不能起到之前的保護作用了。

 

transient變量有什么特點

答:transient是類型修飾符,只能用來修飾字段。在對象序列化的過程中,標記為transient的變量不會被序列化。

super什么時候使用

答:如果父類的構造函數是無參的,那子類構造函數會在第一行默認調用super().

說明一下public static void main(String args[])這段聲明里每個關鍵字的作用

答:

public: main方法是Java程序運行時調用的第一個方法,因此它必須對Java環境可見。所以可見性設置為public.

static: Java平台調用這個方法時不會創建這個類的一個實例,因此這個方法必須聲明為static

void: main方法沒有返回值。

String:是命令行傳進參數的類型,args:是指命令行傳進的字符串數組。

請說出作用域public, private, protected, 以及不寫時的區別

答:private修飾的成員變量和函數只能在類本身和內部類中被訪問。

protected 修飾的成員變量和函數能被類本身、子類及同一個包中的類訪問。

public修飾的成員變量和函數可以被類、子類、同一個包中的類以及任意其他類訪問。

默認情況(不寫)下,屬於一種包訪問,即能被類本身以及同一個包中的類訪問。

 

 

 

 

 

 

 

 

下面這個表能清楚的說明java中作用域操作符的作用:

 作用域       當前類    同一package      子孫類     其他package
  public            √                √                   √                √

  protected      √                √                    √                ×

  friendly         √                 √                    ×                ×

  private          √                 ×                    ×                ×

                    

sizeof Java 的關鍵字嗎

static

 

static class non static class的區別

答:如果把類比喻成雞蛋,內部類為蛋黃,外部類是蛋殼。那么靜態類相當於熟雞蛋,就算蛋殼破碎(外部類沒有實例化),蛋黃依然完好(內部類可以實例化);而非靜態類相當於生雞蛋,蛋殼破碎(無實例化),蛋黃也會跟着xx(不能實例化)。

靜態類型有什么特點static 關鍵字是什么意思?

方便在沒有創建對象的情況下來進行調用(方法/變量)。

main() 方法為什么必須是靜態的?能不能聲明 main() 方法為非靜態

答:Main方法作為程序的入口方法,在這之前是不可能有任何對象被建立的,也就在Main之前包括Main自身不可能是非靜態方法。所以Main方法一定是靜態的

是否可以從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用

不可以。因為非static方法是要與對象關聯在一起的,必須創建一個對象后,

 *    才可以在該對象上進行方法調用,而static方法調用時不需要創建對象,可以

 *    直接調用。也就是說,當一個static方法被調用時,可能還沒有創建任何實例

 *    對象,如果從一個static方法中發出對非static方法的調用,那個非static

 *    方法是關聯到哪個對象上的呢?這個邏輯無法成立,所以,一個static方法內部

 *    發出對非static方法的調用

靜態變量在什么時候加載?編譯期還是運行期?靜態代碼塊加載的時機呢

靜態變量是在類加載的時候分配空間的

成員方法是否可以訪問靜態變量?為什么靜態方法不能訪問成員變量

 

switch

 

switch 語句中的表達式可以是什么類型數據

switch(expression)中,expression只能是一個整數表達式或者枚舉常量,整數表達式可以是int類型或Integer包裝類型。由於,byteshortchar都可以隱式轉換為int類型,所以,這些類型也可以用作表達式。

另外jdk7以后,switch表達式也可以為String類型,

switch 是否能作用在byte 上,是否能作用在long 上,是否能作用在String

 switch可作用於char byte short int

 * switch可作用於char byte short int對應的包裝類

 * switch不可作用於long double float boolean,包括他們的包裝類

 * switch中可以是字符串類型,String(jdk1.7之后才可以作用在string)

 * switch中可以是枚舉類型

 

 

操作符

 

&操作符和&&操作符有什么區別?

&:表示普通與,所有的判斷條件都要依次執行;

&&:若干個條件,如果前面的條件返回false,那么后面不再判斷,就是false;

|:表示普通h或,所有的判斷條件都要依次執行;

||:若干個條件,如果前面的條件返回true,那么后面不再判斷,就是true;

位運算:&表示位與運算,|表示位或計算

 

a = a + b 與 a += b 的區別?

1、對於同樣類型的a,b來說

兩個式子執行的結果確實沒有什么區別。但是從編譯的角度看吧(武讓說的),a+=b;執行的時候效率高。

2、對於不同類型的a,b來說

    2.1    不同類型的兩個變量在進行運算的時候,我們經常說到的是類型的轉換問題。這里,記住兩點:一、運算過程中,低精度的類型向高精度類型轉換。二、如果將高精度的數值賦值給低精度類型變量,則必須要進行顯性的強制轉換。

     2.2    對於a+=b;這個式子,要明確的一點是,+=運算中,結合了強制類型轉換的功能,因此,不會出現編譯錯誤;而對於a=a+b;這個式子,因為是簡單的運算,沒有類型轉換,在編譯過程中會報錯,

 

邏輯操作符 (&,|,^)與條件操作符(&&,||)的區別

a.條件操作只能操作布爾型的,而邏輯操作不僅可以操作布爾型,而且可以操作數值型

b.邏輯操作不會產生短路.

 

3*0.1 == 0.3 將會返回什么?true 還是 false?

false,因為有些浮點數不能完全精確的表示出來。

 

float f=3.4; 是否正確?

原因:精度不准確,應該用強制類型轉換,如下所示:float f=(float)3.4 或float f = 3.4f

 

short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?

對於short s1 = 1; s1 = s1 + 1; 由於s1+1運算時會自動提升表達式的類型,所以結果是int型,再賦值給short類型s1時,編譯器將報告需要強制轉換類型的錯誤。對於short s1 = 1; s1 += 1;由於 += 是java語言規定的運算符,java編譯器會對它進行特殊處理,因此可以正確編譯。

 

 

 

數據結構

 

基礎類型(Primitives)

 

基礎類型(Primitives)與封裝類型(Wrappers)的區別在哪里?

1.基本類型只能按值傳遞,而每個基本類型對應的封裝類是按引用傳遞的。

2.從性能上說java中的基本類型是在堆棧上創建的,而所有的對象類型都是在堆上創建的,(對象的引用在堆棧上創建)。

3.封裝類的出現,是為了更方便的使用一些基本類型不具備的方法,比如valueOf(),toString()等等。

4.如果想傳遞一個int對象的引用,而不是值,那只能用封裝類。

5.基本數據可以自動封裝成封裝類,基本數據類型的好處就是速度快(不涉及到對象的構造和回收),封裝類的目的主要是更好的處理數據之間的轉換,方法很多,用起來也方便。

 

注意:

[在堆棧上分配內存的調用效率和在堆上分配內存的效率差太多了。雖然在堆棧上分配內存效率高,不過在堆棧上分配內存有內存泄露的問題。]

簡述九種基本數據類型的大小,以及他們的封裝類

float和double的默認值是多少?

 

基本類型

大小(字節)

默認值

封裝類

byte

1

(byte)0

Byte

short

2

(short)0

Short

int

4

0

Integer

long

8

0L

Long

float

4

0.0f

Float

double

8

0.0d

Double

boolean

-

false

Boolean

char

2

\u0000(null)

Character

void

-

-

Void

 

 

 

int 和 Integer 哪個會占用更多的內存?

Integer 對象會占用更多的內存。Integer 是一個對象,需要存儲對象的元數據。

 

 

但是 int 是一個原始類型的數據,所以占用的空間更少。

 

int 和 Integer 有什么區別?

1、Integer是int的包裝類,int則是java的一種基本數據類型

2、Integer變量必須實例化后才能使用,而int變量不需要

3、Integer實際是對象的引用,當new一個Integer時,實際上是生成一個指針指向此對象;而int則是直接存儲數據值

4、Integer的默認值是null,int的默認值是0

 

parseInt()函數在什么時候使用到?

parseInt() 函數可解析一個字符串,並返回一個整數。

轉換函數:把字符串轉換為整數。

默認情況下,以字符串形式存儲。

 

如何去小數四舍五入保留小數點后兩位

import java.math.BigDecimal;

import java.text.DecimalFormat;

import java.text.NumberFormat;

public class format {

    double f = 111231.5585;

    public void m1() {

        BigDecimal bg = new BigDecimal(f);

        double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        System.out.println(f1);

    }

    /**

     * DecimalFormat轉換最簡便

     */

    public void m2() {

        DecimalFormat df = new DecimalFormat("#.00");

        System.out.println(df.format(f));

    }

    /**

     * String.format打印最簡便

     */

    public void m3() {

        System.out.println(String.format("%.2f", f));

    }

    public void m4() {

        NumberFormat nf = NumberFormat.getNumberInstance();

        nf.setMaximumFractionDigits(2);

        System.out.println(nf.format(f));

    }

    public static void main(String[] args) {

        format f = new format();

        f.m1();

        f.m2();

        f.m3();

        f.m4();

    }

}

 

 

結果:

111231.56

111231.56

111231.56

111,231.56

 

char 型變量中能不能存貯一個中文漢字,為什么

char型變量是用來存儲Unicode編碼的字符的,unicode編碼字符集中包含了漢字,

 * 所以,char型變量中當然可以存儲漢字啦。不過,如果某個特殊的漢字沒有被包含在

 * unicode編碼字符集中,那么,這個char型變量中就不能存儲這個特殊漢字。補充

 * 說明:unicode編碼占用兩個字節,所以,char類型的變量也是占用兩個字節

 

類型轉換

 

怎樣將 bytes 轉換為 long 類型

怎么將 byte 轉換為 String

byte[] srtbyte;

String res = new String(srtbyte);

System.out.println(res);

 

如何將數值型字符轉換為數字

使用對象包裝類,如Integer.parseInt("1234")

 

我們能將 int 強制轉換為 byte 類型的變量嗎?如果該值大於 byte 類型的范圍,將會出現什么現象?

  因為Java中byte是用8位來存儲,只能表示-128~127之間的數,當由int強制類型轉化為byte時,系統就采取了截取int后8位的做法。

 

能在不進行強制轉換的情況下將一個 double 值賦值給 long 類型的變量嗎

java double轉long型是取整運算;

 

 

數組

 

如何權衡是使用無序的數組還是有序的數組

有序數組最大的好處:在於查找的時間復雜度是O(log n),而無序數組是O(n)。

有序數組的缺點是:插入操作的時間復雜度是O(n),因為值大的元素需要往后移動來給新元素騰位置。相反,無序數組的插入時間復雜度是常量O(1)。

 

怎么判斷數組是 null 還是為空

int b[]=null;

int a[] = new int [10];

System.out.println("a數組的長度:"+a.length);

System.out.println("b數組的長度:"+b.length);//會空指針異常;

 

Array 和 ArrayList有什么區別?什么時候應該使用Array而不是ArrayList

存儲內容比較:

Array數組可以包含基本類型和對象類型,

ArrayList卻只能包含對象類型。

但是需要注意的是:Array數組在存放的時候一定是同種類型的元素。ArrayList就不一定了,因為ArrayList可以存儲Object。

 

 

空間大小比較:

它的空間大小是固定的,空間不夠時也不能再次申請,所以需要事前確定合適的空間大小。

ArrayList的空間是動態增長的,如果空間不夠,它會創建一個空間比原空間大一倍的新數組,然后將所有元素復制到新數組中,接着拋棄舊數組。而且,每次添加新的元素的時候都會檢查內部數組的空間是否足夠。(比較麻煩的地方)。

 

方法上的比較:

ArrayList作為Array的增強版,當然是在方法上比Array更多樣化,比如添加全部addAll()、刪除全部removeAll()、返回迭代器iterator()等。

適用場景:

如果想要保存一些在整個程序運行期間都會存在而且不變的數據,我們可以將它們放進一個全局數組里,但是如果我們單純只是想要以數組的形式保存數據,而不對數據進行增加等操作,只是方便我們進行查找的話,那么,我們就選擇ArrayList。而且還有一個地方是必須知道的,就是如果我們需要對元素進行頻繁的移動或刪除,或者是處理的是超大量的數據,那么,使用ArrayList就真的不是一個好的選擇,因為它的效率很低,使用數組進行這樣的動作就很麻煩,那么,我們可以考慮選擇LinkedList。

 

數組和鏈表數據結構描述,各自的時間復雜度?

1、存取方式上,數組可以順序存取或者隨機存取,而鏈表只能順序存取; 

2、存儲位置上,數組邏輯上相鄰的元素在物理存儲位置上也相鄰,而鏈表不一定; 

3、存儲空間上,鏈表由於帶有指針域,存儲密度不如數組大; 

4、按序號查找時,數組可以隨機訪問,時間復雜度為O(1),而鏈表不支持隨機訪問,平均需要O(n); 

5、按值查找時,若數組無序,數組和鏈表時間復雜度均為O(1),但是當數組有序時,可以采用折半查找將時間復雜度降為O(logn); 

6、插入和刪除時,數組平均需要移動n/2個元素,而鏈表只需修改指針即可; 

7、空間分配方面: 
  數組在靜態存儲分配情形下,存儲元素數量受限制,動態存儲分配情形下,雖然存儲空間可以擴充,但需要移動大量元素,導致操作效率降低,而且如果內存中沒有更大塊連續存儲空間將導致分配失敗; 
  鏈表存儲的節點空間只在需要的時候申請分配,只要內存中有空間就可以分配,操作比較靈活高效

 

 

數組有沒有length()這個方法? String有沒有length()這個方法

數組中沒有length()這個方法,但是數組中有length這個屬性。用來表示數組的長度。

String中有length()這個方法。用來得到字符串的長度。

 

隊列

 

隊列和棧是什么,列出它們的區別

隊列先進先出,棧先進后出。

棧(Stack)是限定只能在表的一端進行插入和刪除操作的線性表。

隊列(Queue)是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。

 

ArrayList、Vector、LinkedList的存儲性能和特性

1.ArrayList 采用的是數組形式來保存對象的,這種方式將對象放在連續的位置中,所以最大的缺點就是插入刪除時非常麻煩.

2.LinkedList 采用的將對象存放在獨立的空間中,而且在每個空間中還保存下一個鏈接的索引 但是缺點就是查找非常麻煩 要叢第一個索引開始

3.ArrayList和Vector都是用數組方式存儲數據,此數組元素數要大於實際的存儲空間以便進行元素增加和插入操作,他們都允許直接用序號索引元素,但是插入數據元素涉及到元素移動等內存操作,所以索引數據快而插入數據慢.

4.Vector使用了sychronized方法(線程安全),所以在性能上比ArrayList要差些.

5.LinkedList使用雙向鏈表方式存儲數據,按序號索引數據需要前向或后向遍歷數據,所以索引數據慢,是插入數據時只需要記錄前后項即可,所以插入的速度快.

6.arraylist和vector的區別?

1).同步性:Vector是線程安全的,也就是說是同步的,而ArrayList是線程不安全的,不是同步的

2).數據增長:當需要增長時,Vector默認增長為原來一培,而ArrayList卻是原來的一半

3).Vector不能有種復的值,ArrayList則可有重復的值。

 

 

 

String

StringBuffer

StringBuilder

  1. 三者在執行速度方面的比較:StringBuilder >  StringBuffer  >  String
  2. StringBuilder:線程非安全的
  3. StringBuffer:線程安全的
  4. 如果要操作少量的數據用 = String
  5. 單線程操作字符串緩沖區 下操作大量數據 = StringBuilder
  6. 多線程操作字符串緩沖區 下操作大量數據 = StringBuffer

 

HashMap

 

HashMap的工作原理是什么?

通過hash的方法,通過putget存儲和獲取對象。存儲對象時,我們將K/V傳給put方法時,它調用hashCode計算hash從而得到bucket位置,進一步存儲,HashMap會根據當前bucket的占用情況自動調整容量(超過Load Facotrresize為原來的2)。獲取對象時,我們將K傳給get,它調用hashCode計算hash從而得到bucket位置,並進一步調用equals()方法確定鍵值對。如果發生碰撞的時候,Hashmap通過鏈表將產生碰撞沖突的元素組織起來,在Java 8中,如果一個bucket中碰撞沖突的元素超過某個限制(默認是8),則使用紅黑樹來替換鏈表,從而提高速度。

 

HashMap、LinkedMap、TreeMap的區別

A:HashMap 參考其他問題;

LinkedHashMap 保存了記錄的插入順序,在用 Iterator 遍歷時,先取到的記錄肯定是先插入的;遍歷比 HashMap 慢;

TreeMap 實現 SortMap 接口,能夠把它保存的記錄根據鍵排序(默認按鍵值升序排序,也可以指定排序的比較器)

 

Set

 

Set 里的元素是不能重復的,那么用什么方法來區分重復與否呢?是用 == 還是 equals()? 它們有何區別?

 

1、什么是Set?(what)

     Set是Collection容器的一個子接口,它不允許出現重復元素,當然也只允許有一個null對象。

 

2、如何來區分重復與否呢?(how)

 

     “ 用 iterator() 方法來區分重復與否 ”,這是在網上流傳的答案,個人認為這是個錯誤的答案。API中寫的很明白:“set 不包含滿足

e1.equals(e2) 的元素對 e1 和 e2 ”,由此可見回答使用equals()區分更合適。

 

3、為什么用equals()而不用==來區分?(why)

 

     應該從它倆的區別談起,==是用來判斷兩者是否是同一對象(同一事物),而equals是用來判斷是否引用同一個對象。再看一下Set里面存的是

對象,還是對象的引用。根據java的存儲機制可知,set里面存放的是對象的引用,所以當兩個元素只要滿足了equals()時就已經指向同一個對象,

也就出現了重復元素。所以應該用equals()來判斷。

 

List

 

List, Set, Map三個接口,存取元素時各有什么特點?

List與Set都是單列元素的集合,它們有一個功共同的父接口Collection。

Set里面不允許有重復的元素,

存元素:add方法有一個boolean的返回值,當集合中沒有某個元素,此時add方法可成功加入該元素時,則返回true;當集合含有與某個元素equals相等的元素時,此時add方法無法加入該元素,返回結果為false。

取元素:沒法說取第幾個,只能以Iterator接口取得所有的元素,再逐一遍歷各個元素。

 

List表示有先后順序的集合,

存元素:多次調用add(Object)方法時,每次加入的對象按先來后到的順序排序,也可以插隊,即調用add(int index,Object)方法,就可以指定當前對象在集合中的存放位置。

取元素:方法1:Iterator接口取得所有,逐一遍歷各個元素

 

        方法2:調用get(index i)來明確說明取第幾個。

 

Map是雙列的集合,存放用put方法:put(obj key,obj value),每次存儲時,要存儲一對key/value,不能存儲重復的key,這個重復的規則也是按equals比較相等。

取元素:用get(Object key)方法根據key獲得相應的value。

 

        也可以獲得所有的key的集合,還可以獲得所有的value的集合,

 

        還可以獲得key和value組合成的Map.Entry對象的集合。

List以特定次序來持有元素,可有重復元素。Set 無法擁有重復元素,內部排序。Map 保存key-value值,value可多值。

 

List, Set, Map 是否繼承自 Collection 接口

遍歷一個 List 有哪些不同的方式

List遍歷方式:

第一種:

for(Iterator iterator = list.iterator();iterator.hasNext();){                    

    int i = (Integer) iterator.next();                   

    System.out.println(i);               

}

第二種:

Iterator iterator = list.iterator();

while(iterator.hasNext()){

    int i = (Integer) iterator.next();

    System.out.println(i);

}

第三種:

for (Object object : list) {

    System.out.println(object);

}

第四種:

for(int i = 0 ;i<list.size();i++) {  

    int j= (Integer) list.get(i);

    System.out.println(j);  

}

 

LinkedList

 

LinkedList 是單向鏈表還是雙向鏈表

雙向鏈表

LinkedList 與 ArrayList 有什么區別

 1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。

 2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指針。

 3.對於新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據

描述下 Java 中集合(Collections),接口(Interfaces),實現(Implementations)的概念。

插入數據時,ArrayList, LinkedList, Vector誰速度較快?

ArrayList和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由於使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。

 

ArrayList

 

ArrayList 和 HashMap 的默認大小是多數?

List 元素是有序的、可重復

 

ArrayList、Vector默認初始容量為10

 

Vector:線程安全,但速度慢

 

    底層數據結構是數組結構

 

    加載因子為1:即當 元素個數 超過 容量長度 時,進行擴容

 

    擴容增量:原容量的 1倍

 

      如 Vector的容量為10,一次擴容后是容量為20

 

ArrayList:線程不安全,查詢速度快

 

    底層數據結構是數組結構

 

    擴容增量:原容量的 0.5倍+1

 

      如 ArrayList的容量為10,一次擴容后是容量為16

 

 

 

Set(集) 元素無序的、不可重復。

 

HashSet:線程不安全,存取速度快

 

     底層實現是一個HashMap(保存數據),實現Set接口

 

     默認初始容量為16(為何是16,見下方對HashMap的描述)

 

     加載因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容

 

     擴容增量:原容量的 1 倍

 

      如 HashSet的容量為16,一次擴容后是容量為32

 

 

 

Map是一個雙列集合

 

HashMap:默認初始容量為16

 

     (為何是16:16是2^4,可以提高查詢效率,另外,32=16<<1       -->至於詳細的原因可另行分析,或分析源代碼)

 

     加載因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容

 

     擴容增量:原容量的 1 倍

 

      如 HashSet的容量為16,一次擴容后是容量為32


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM