您好,登錄后才能下訂單哦!
八種基本數據類型的大小,以及他們的封裝類
整數型: byte 1個字節 -128~127 封裝類:Byte
short 2個字節 -32768~32767 Short
Int 4個字節 -2147483648~2147483647 Integer
long 8個字節 -2的63方~2的63次方-1 Long
浮點型: float 4個字節 單精度 Float
Double 8個字節 雙精度 Double
布爾類型: boolean 4個字節 true或false Boolean
字符類型: char 2個字節 Character
引用數據類型:
分為3種,類、接口和數組
Switch能否用String做參數
在jdk7以前,switch只支持byte、int、short、char或者對應的包裝類和枚舉。
equals和==的區別
a) 對象類型不同 equals是超類Object的方法,而==是操作符
b) 比較類型不同 equals用來檢測兩個對象是否相同,即兩個對象的內容是否相等,==比較引用數據類型和基本數據類型時具有不同的功能。==比較的是變量(棧)內存中存放的對象的內存地址,用來判斷兩個對象的地址是否相同,即是否指向同一對象,比較的是真正意義上的指針操作,而equals用來比較的是兩個對象的內容是否相同,適用于所有對象。
c) 注意:如果沒有對該對象進行覆蓋的話,調用的仍然是超類Object的方法,而Object中的equals方法返回的是==的判斷。
自動拆裝箱和常量池
a) Java自動將原始數據類型值轉換成對應的對象,比如將int類型的變量轉換成Integer類型,自動裝箱時調用valueOf將原始數據類型轉換成對應的對象。
b) 反之,將Integer對象裝換成int類型值,這個過程叫拆箱,自動拆箱通過調用類似intValue、doubleValue這類的方法將對象轉換成對應的原始數據類型。
c) Java中的常量池,實際上分為兩種形態:靜態常量池和運行時常量池。
i. 靜態常量池:即.*class文件中的常量池,class文件中的常量池不僅僅包含字符串,還包含類、方法的信息,占用class文件絕大部分空間。
ii. 而運行時常量池:則是jvm虛擬機在完成類裝載過程后,將class文件中的常量池載入到內存中,并保存在方法區中,我們常說的常量池就是指方法區中的運行時常量池。
Object中有哪些公用方法?
a) Clone:實現對象的淺復制,只有實現了cloneable接口才可以調用此方法,否則會拋出CloneNotSupportedException異常。
b) Equals:在Object中和==是一樣的,子類一般需要重寫此方法。
c) Hashcode:該方法用于哈希查找,重寫了equals方法一般都要重寫hashcode方法,這個方法在一些具有哈希功能的collection中用到。
d) getClass:獲得運行時的類型。
e) wait:是當前線程等待該對象的鎖,當前線程必須是該對象的擁有者,也就是說具有該對象的鎖!
f) Notify:喚醒在對象上等待的某個線程。
g) notifyAll:喚醒該對象上等待的所有線程。
h) toString:轉換成字符串,一般子類都要重寫此方法,否則打印句柄。
Java的四種引用,強弱軟虛。
a) 強引用:最常見,把一個對象賦給引用數據類型則為強引用。如果內存中不足,java虛擬機將會跑出OutOfMemoryError錯誤,從而將程序異常停止強引用的對象是不可以gc回收的,不可以隨意回收具有強引用的對象來解決內存不足的問題。在java中,強引用是一種默認的狀態,除非Java虛擬機停止工作。
b) 軟引用:如果一個對象具有軟引用,內存空間足夠,垃圾回收就不會回收它,如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序繼續使用。軟引用用來實現內存敏感的高速緩存,比如網頁緩存或圖片緩存,使用軟引用能防止內存泄露,增強程序的健壯性。
c) 弱引用:用來描述非必需對象的,當jvm進行垃圾回收的時候,無論內存是否充足,都會回收被弱引用關聯的對象。
d) 虛引用:他不影響對象的生命周期,如果一個對象與虛引用關聯,則跟沒有與之關聯一樣,在任何時候都可能被垃圾回收器回收。
hashcode的作用
比較兩個對象是否相等,重寫的equals方法一般比較全面,比較復雜,效率比較低,而采用hashcode方法進行對比,只需要生成一個hashcode進行比較就可以了!
Hashmap中的hashcode的作用
a) Hashcode的存’用于查找的快捷性,如hashtable、hashmap等,hashcode是在散列結構中確定對象的地址。
b) 如果兩個對象相同,就是適用equals方法,那么這兩個對象的hashcode一定要相同。
c) 如果對象的equals方法被重寫,那么對象的hashcode也盡量重寫,并且產生hashcode使用的對象,一定要和equals放法使用的一致,否則會違反上面的第二點。
d) 兩個對象的hashcode相同,并不代表這兩個對象就相同,也就是不一定適用equals方法,只能說明這兩個對象在散列存儲結構中,如hashtable,他們“存放在同一個籃子里”。
為什么重載hashcode方法?
一般不需要重載hashcode方法,只有當類放在hshtable、hashmap、hashset等hash結構的集合時,才會重載hashcode。就hashmap來說,好比hashmap就是一個大內存塊,里面有許多小內存塊,小內存里面就是一系列的對象,可以利用hashcode查找小內存塊,,所以當equals相等時,hashcode必需相等,而且如果是Object對象,必須重載hashcode和equals方法。
Arraylist、linkedlist和vector的區別?
a) Arraylist:底層數據結構是數組,查詢快、增刪慢,線程不安全。
b) Liskedlist;底層數據結構是鏈表,查詢慢、增刪塊,線程不安全。
c) Vector:底層是數組,查詢慢、增刪慢,線程安全。
String、stringbuffer與stringbulder的區別?
a) String是不可變的對象,因此每次對string類型進行改變的時候,就等于生成了一個新的對象,然后蔣指針指向一個新的string的對象,因此經常改變內容的字符串最好不用string,因為每次生成對象都會對系統性能產生影響,特別是當內存中無引用對象過多時,jvm的gc就會開始工作,那么速度一定會非常慢。
b) 而stringbuffer結果就完成不一樣了,每次結果都會對stringbuffer本省進行操作,而不是生成新的對象,再改變對象的引用。是線程安全的。
c) Stringbuildere是jdk5以后新增的,其用法和stringbuffer完全一致,但它是線程不安全的,在單線程中是最佳的,因為不需要維護線程的安全。
Map、set、list、queue、stack的特點與用法。
a) Map是鍵值對,鍵key是唯一不能重復的,一個鍵對應一個值,值可以重復,treemap可以保證順序,hashmap不保證順序,即是無序的,map可以把key和value單獨抽取出來,其中keyset()方法可以將所存的key抽取成一個set。而valuses方法可以將map中所有的value抽取成一個集合。
b) Set:不包含重復元素,且最多包含一個null元素,只能用iterater實現單向遍歷, set沒有同步方法。
c) List:有序的可重復集合,可以在任何位置增加和刪除元素。用Iterator實現單向遍歷,也可以用listIterator實現是雙向遍歷。
d) Queue:遵從先進先出原則,使用時盡量避免add()和remove()方法,而只是使用offer()來添加元素,使用poll來移除元素,它的優點是可以通過返回值來判斷是否成功,LinkedList實現Queue接口,Queue通常不允許插入null元素。
e) Stack:遵從先進后出原則,stack繼承自vector,它通過五個操作對類vector進行擴展,允許將向量視為堆棧,它提供push和pop操作,以及取堆棧頂點的peek()方法,測試堆棧是否為空的empty()方法等。
f) 用法:如果涉及堆棧、隊列等操作,建議使用list,對于快速插入和刪除元素,建議使用linkedlist,如果,快速隨機訪問元素,建議使用ArrayList。
Hashmap和hashtable的區別?
a) 都是map接口的實現類,都是基于hash表的實現類。
b) Hashmap集合線程不安全的類,不同步,執行效率高,允許鍵和值是null。
c) Hashtable集合是線程安全的類,同步,執行效率低,不允許鍵和值為null。
Jdk7和jdk8中的hashmap的實現。
a) Jdk7:hashmap底層維護一個數組,數組中的每一項都是一個entry,我們向hashmap中放置的對象實際上存儲在該數組中,map中的key和value則以entry的形式存放在數組中,而這個key放在數組的哪一個位置上,是通過key的hashcode來計算的。
b) Jdk8:采用(位桶+鏈表)紅黑樹的方式,也是非線程安全的。
Hashmap和hashConcurrentHashmap的區別,hashmap的底層源碼。
Hashmap是線程非安全的,效率比較高,hashtable和ConcurrentHashmap是線程安全的,效率比hashmap差一點,但ConcurrentHashmap采用了更高級的分段鎖機制,具體可以理解為把hashmap拆分為n個小的hashtable,根據key。Hashcode()來決定把key放到哪個hashtable中,在concurrenthashmap中,就是把map分為n個segment,put和get時,都是key.hashcode()算出放到哪個segment中。
接口和繼承的區別?接口內可以定義常量嗎?繼承可以繼承父類的那些東西?
a) 區別:
i. 標識符不同,interface和extends
ii. 接口支持多繼承,而不支持繼承的繼承
iii. 接口中只能定義全局變量和抽象變量,而繼承中可以定義屬性、方法、常量、變量等。
iv. 某接口被實現,在類中一定要實現接口所有的方法,而繼承只需要用哪一個就調用哪一個。
b) 接口不可以定義常量。
c) 繼承可以繼承父類所有的東西(成員方法、成員變量、包括私有)。
如何修改父類中以private關鍵字修飾的變量?
如果父類中有public的set方法,就可以通過set方法修改父類中以private修改的變量。
Java中public、private 、protect、default的區別?
a) Public:java中訪問限制最寬的修飾符,即公共的,被修飾的類、屬性、方法允許跨類訪問,甚至可以跨包訪問。
b) Private:是java中訪問限制最窄的修飾符,被private修飾的類、屬性、方法只能被本類的對象進行訪問,其子類不能訪問,更不允許跨包訪問。
c) Protec:介于public和private之間的一種訪問修飾符,一般稱受保護的,被其修飾的類、方法、屬性只能被本類和子類進行訪問,即使子類不在同一個包下。
d) Default:意為默認的,即不加修飾符,該模式下只能同一個包下進行訪問。
數據庫鎖的問題?如何上鎖?是不是行鎖?
a) 當多個用戶同時對數據庫進行操作時,會帶來數據不一致的問題,所以鎖主要是用于多用戶環境下保證數據庫完整性和一致性.
b) 鎖分類:從數據庫系統來看:排它鎖、悲觀鎖、更新鎖
從程序員角度來看:一種是樂觀鎖,一種是悲觀鎖。
i. 悲觀鎖:很悲觀,每次去拿數據的時候,都以為別人會修改,所以在每次拿數據的時候,都會上鎖,這樣別人拿這個數據就會block,直到它合鎖。具有強烈的排他性和獨占性,悲觀鎖的實現依靠數據庫提供的機制,也只有數據庫底層提供的機制才能保證數據訪問的排他性。傳統的關系型數據庫用到了很多這同樣的機制,比如行鎖、表鎖、讀鎖、寫鎖等,都是在操作前加上鎖。
ii. 樂觀鎖:很樂觀,每次去拿數據的時候都認為別人不會修改,所以不會上鎖,但是在更新的時候會判斷一下在此期間別人有沒有去更新這個數據,可以使用版本號等機制。悲觀鎖適用于多讀的應用類型,這樣可以提高吞吐量,像數據庫如果提供類似于write—condition機制的其實都是提供的樂觀鎖。
c) 按作用性質分:
i. 共享鎖:也叫讀鎖,用于所有只讀操作,不能同時增刪改,可以查。
例如:select * from 表 lock in share mode;
ii. 排它鎖:也叫讀鎖,表示對數據進行寫操作,一個事務對象施加了排它鎖,其他事務就不能加鎖了。
例如:查詢時加排它鎖,別人不能加共享鎖和排它鎖。
Select * from 表 for update;
僅允許一個事務封鎖此表,其他事務必須等到此鎖被釋放才能訪問。
排它鎖(x鎖)一直到事務結束才能釋放。
iii. 更新鎖:允許其他事務讀,但不允許在施加x鎖和u鎖,當要被讀取的對象要被更新的時候,則升級為x鎖,防止死鎖,如果一個數據在修改前直接申請更新鎖,在修改時再升級為排它鎖,就可以避免死鎖。
d) 按范圍分:
i. 行鎖:鎖的范圍是行級別,數據能夠確定哪些行需要鎖的情況下使用行鎖(inodb),如果在不知道會影響到哪些數據的時候就會使用表鎖
例如:一個用戶表有主鍵id和birthday。
Update …where id=? 行鎖
Update … where birthday=? 表鎖
ii. 表鎖:鎖的范圍是整張表。 MyISAM
22.事務的隔離性
a) 隔離性級別越低,并發性越好,但數據庫的一致性就越差。
隔離級別越高,并發性越差,但數據庫的一致性高。
b) 由低到高
讀未提交<讀提交<可重復讀(默認)<序列化讀
c) 錯誤的級別由低到高:
臟讀、不可重復讀、幻讀
臟讀:兩個事物,一個事務先修改,另一個事務讀,結果是修改前的結果。
不可重復讀:兩個事物,一個先讀是一個結果,一個后修改,再讀,又是一個結果。
幻讀:第一個事務表中有10、20、30、40幾個部門,第二個事務插入表中50的部門,然后提交,第一個事務插入50部門,主鍵沖突。
23.能否用一個sql語句解決庫存判斷問題(非查詢語句)。
用if語句:if(exper1,exper2,exper3)
如果exper1的值是true,則返回是exper2的值,如果exper1的值是false,則返回exper3的值。
例如:id name number
1 蘋果 300
2 梨 100
Update fruit set number=if(number>200,number,0)where if=’1’;
即如果蘋果的數量大于200,就不變,否則,number改為0,即就可以判斷內存是否充足。
24.紅黑樹
a) 特性:
i. 每個節點都是黑色或者紅色。
ii. 根節點是黑色。
iii. 定義null為黑色。
iv. 如果某個子節點是紅色,那么它的兩個兒子都是黑色,且父節點一定是黑色。
v. 對于任意節點,它到葉子節點的每一條路徑都包含相同數目的黑色節點
性質5稱之為黑高。
b) 相對平衡:
i. 若H(left)>=H(right),則H(left)=2*H(right)+1
ii. 但BH(left)=BH(right),H(left)<H(right)同理。
c) 在調整節點p之前,必需保證p的左子樹left、右子樹right都已經是rbt。
i. 多個子問題成立->某個總問題成立
ii. 插入調整:刪除調整均是由底向上
d) Rbt的插入調整(默認是紅色)
i. 無需調整
ii. 僅僅考慮父親節點p是紅色,由于性質4,爺爺節點必定是黑色,分為3中:
1. Case1:y為黑色,x可左可右;p、y染黑,g染紅;x回溯至g
2. Case2:y為黑色,x為右孩子,左旋p,x指向p,轉為case3
3. Case3:y為黑色,x為左孩子,p染黑,g染紅,右旋g結束。
Rbt的插入調整最多2次
右旋轉:逆時針旋轉兩個節點,使父親節點被右孩子取代,而自己變成左孩子。
左孩子:順時針旋轉兩個子節點,使父親節點被左孩子取代,自己變成右孩子。
25.Session是什么?和cookie的區別?
a) Cookie通過客戶端記錄信息確認身份,session是通過服務端的信息確認身份。
b) 客戶端瀏覽器訪問服務器的時候,服務端把客戶端的信息以某種形式記錄在服務器上,這就是session,用戶與服務器建立連接的同時,服務器自動分配一個sessionid。
c) 區別:cookie不×××全,別人可以分析本地存在的cookie并進行cookie欺騙,考慮到安全應當使用session。
有哪些排序算法?說一下堆排序?時間復雜度是多少?
a) 直接插入排序:第一個元素已經排序,第二個與第一個元素進行比較,第一個大,第一個則與第二個交換位置,第三個分別于第一個和第二個比較,以此類推。
時間復雜度:O(n*n)
b) 希爾排序:按步長grep進行分組,然后將每組元素利用直接插入排序的方法進行排序;每一次結束后再將步長grep減半,循環上述操作,直到步長grep=1,利用直接插入排序,完成排序。
時間復雜度:O(log n)
c) 簡單選擇排序:首先在未排序序列中找到最小(或最大)的元素,放在排序序列的起始位置,然后再從未排序序列中找到最小(最大)的元素,放在已排序序列的后面。
時間復雜度:O(n*n)
d) 堆排序:堆排序過程就是將待排序序列構造成一個堆,選出堆中最大的移走,再把剩下的整成堆,找出最大的在移走,重復直至有序。
i. 每次將根節點與左右節點最大的進行交換,直到根節點最大,然后把根節點放在最后一個位置,然后再次執行循環,找到最大值放在長度-1的位置。
ii. 時間復雜度:O(n log n)
e) 冒泡排序:每次比較兩個元素,把小的放在前面。
時間復雜度:O(n*n)
f) 快速排序:把一個序列分為兩個子序列,步驟可分為:
i. 從數列中選出一個元素,作為基準。
ii. 重新排序數列,所有比基準序列小的元素放在基準前面,所有比基準大的元素放在基準后面,相同的放在任意一邊,在這個分區結束后,該基準處于中間位置。
iii. 遞歸將小于基準的子序列和大于基準的子序列排序。
iv. 即:先對大序列進行排序,大序列分為兩個子序列,然后遞歸調用方法對這兩個序列進行排序。
g) 歸并排序:將兩個或兩個以上的有序表合并成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列都是有序的,然后再把整個序列合并成整體有序序列。
時間復雜度:O(nlogn)
h) 基數排序:將所有待比較的數(正整數統一為同樣的數位長度),數位數不足的前面補0,然后從低位開始,依次進行一次排序,這個序列從最低位排序一直到最高位排序完成以后,數列將變成一個有序序列。
時間復雜度:O(d*(n+r))
D為位數,r為基數,n為數據個數
27.Statement和preparestatement的區別?
a) 代碼的可讀性和可維護性preparestatement更好。
b) Preparestatement盡最大可能提高性能。
c) 提高安全性,preparestatement防止sql注入。
28.NIO和IO到底有什么區別?有什么關系?
a) NIO是以塊的方式處理數據,但是IO是以最基礎的字節流的形式去寫入和讀出的,肯定NIO的效率比IO的效率高出好多。
b) NIO不是和IO一樣用Ouputstream和Inputstream輸入流形式來處理數據,但是基于這種流的形式,而是采用通道和緩沖流的形式來處理數據的。
c) NIO通道可以是雙向的,IO中的流只能是單向的。
d) 還有就是NIO的緩沖區(其實也是一個字符數組)還可以進行分片,可以建立只讀緩沖區、直接緩沖區和間接緩沖區,只讀緩沖區很明顯就字面意思,直接緩沖區是為了加快I/O速度,而以一種特殊的方式分配其內存的緩沖區。
29.數據庫索引的分類,索引底層的實現,說一下b+樹,b-樹?
a) 索引的作用:
i. 提高查詢速度
ii. 確保數據的唯一性
iii. 可以加快表與表之間的連接,實現表和表之間的完整性。
iv. 使用分組和排序字句進行數據檢查時,可以減少分組和排序的時間。
v. 全文檢索字段進行搜索優化。
b) 分類;
i. 主鍵索引(PRIMAY_KEY):確保數據記錄的唯一性,一個表只有一個。
ii. 唯一索引(UNIQUE):避免一個表中某些數據列中的值重復。可以有多個。
iii. 常規索引(INDEX):快速定位特定數據。
iv. 全文索引(FULLTEXT):快速定位特定數據,只能用于MyISAM類型的數據表。
c) 索引底層實現:把平衡樹當做數據表默認的索引數據結構,平衡樹也就你、b+tree或者b-tree。
d) B-tree:適用于外查找的樹,是平衡樹的多叉樹。
i. 一個m階b樹是一顆平衡的m路搜索樹,它或者是空樹,或者滿足下列性質:
1. 定義任意非葉子節點最多有m個兒子,且m>=2;
2. 根節點的兒子數[2,m];
3. 除根節點以外的葉子節點的兒子數{m/2,m};
4. 每個節點存放m/2-1(向上取整)和至多m-1個關鍵字(至少2個)。
5. 非葉子節點的關鍵字個數=指向兒子的指針個數-1;
6. 非葉子節點的關鍵字:k[1]、k{2}…k[m-1],且k{i}<k{i+1}。
7. 非葉子節點的指針:p{1} 、p{2} 、p{3}、 p{4} …p{m},其中p[1】指向小于k[1]的子樹,p[m]指向關鍵字屬于k{i}和k{i+1}之間的子樹。
8. 所有子樹節點位于同一層。
ii. B-樹的特性:
1. 關鍵字集合分布在整棵樹中。
2. 任何一個關鍵字出現且只出現一個節點中。
3. 搜索可能在非葉子節點結束。
4. 其搜索性能等價于在在關鍵字全集中做一次二分查找。
5. 自動層次控制。
e) B+樹:
i. B+樹的定義:
1. 其定義與b-樹基本相同,除了:
2. 非葉子節點的子樹指針與關鍵字個數相同。
3. 非葉子節點的子樹指針p[i],指向關鍵字屬于k[i],k[i+1]的子樹。
4. 為所有關鍵字增加一個鍵指針。
5. 所有關鍵字在葉子節點出現。
ii. B+樹的特性:
1. 所有關鍵字都出現葉子節點的鏈表中(稠密索引)且鏈表中的關鍵字恰好是有序的。
2. 不可能在非葉子節點命中。
3. 非葉子節點相當于葉子節點的索引(稀疏索引),葉子節點相當于存儲數據(關鍵字)的數據層。
4. 更適合文件索引系統。
30.java類加載的過程。
類從被加載到jvm中開始,到卸載為止,整個生命周期包括:加載、驗證、準備、解析、初始化、使用和卸載七個階段。
其中類加載的過程包括加載、驗證、準備、解析、初始化五個階段。
類加載的任務是根據一個類的全限定名來讀取此類的二進制字節流到jvm中,此后轉換為一個與目標類對應的java.lang.Class對象實例。
bootstrapclassloader、extclassloader和appclassloader defineclass方法將字節碼的byte數組轉換為一個類的class對象實例,如果此類被記載到jvm時就被鏈接,那么就可以調用resolveclass方法
自定義類加載器需要繼承抽象類classloader,實現findclass方法,該方法會在classloader調用的時候被調用,findclass默認會拋出異常。
findclass方法表示根據類名查找類對象。
loadclass方法根據類名進行雙親委托模型進行類加載并返回類對象。
defineclass方法根據類的字節碼轉換為類對象。
雙親委托模型:當一個類接受到一個類加載的任務時,不會立即展開加載,而是將加載任務委托給它的父類加載器去執行,每一層的類都會采用相同的方法,直到委托給最頂層的啟動類加載器為止。如果父類加載器無法加載委托給它的類,便將類的加載任務退回給下一級類加載器去執行加載。
雙親委托模型的工作過程是:如果一個類加載器收到類加載的請求,它不會自己嘗試去加載這個類,而是把這個請求委托給父類加載器去完成,每一層次的類加載器都是如此,因此所有的加載請求都應該傳送到頂層的啟動類加載器中,只有父類加載器反饋自己無法加載這個加載請求時,子加載器才會嘗試自己去加載。
使用雙親委托模型的好處:能夠確保一個類的全局唯一性,當程序中出現多個限定名相同的類時,類加載器在執行加載時,始終只會加載其中的某一個類。
31.Object如果不重寫hashcode()的話,hashcode()如何計算出來的?
Object 的 hashcode 方法是本地方法,也就是用 c 語言或 c++ 實現的,該方法直接返回對象的 內存地址。
32.java8新特性。
(1)Lambda表達式
Lambda表達式可以說是Java 8最大的賣點,她將函數式編程引入了Java。Lambda允許把函數作為一個方法的參數,或者把代碼看成數據。
一個Lambda表達式可以由用逗號分隔的參數列表、–>符號與函數體三部分表示。例如:
Arrays.asList( "p", "k", "u","f", "o", "r","k").forEach( e -> System.out.println( e ) );
(2)接口的默認方法與靜態方法
我們可以在接口中定義默認方法,使用default關鍵字,并提供默認的實現。所有實現這個接口的類都會接受默認方法的實現,除非子類提供的自己的實現。例如:
public interface DefaultFunctionInterface {
default String defaultFunction() {
return "default function";
}
}
(3)方法引用
1)通常與Lambda表達式聯合使用,可以直接引用已有Java類或對象的方法。一般有四種不同的方法引用:
2)構造器引用。語法是Class::new,或者更一般的Class< T >::new,要求構造器方法是沒有參數;
3)靜態方法引用。語法是Class::static_method,要求接受一個Class類型的參數;
4)特定類的任意對象方法引用。它的語法是Class::method。要求方法是沒有參數的;
5)特定對象的方法引用,它的語法是instance::method。要求方法接受一個參數,與不同的地方在于,3是在列表元素上分別調用方法,而4是在某個對象上調用方法,將列表元素作為參數傳入;
(4)重復注解
在Java 5中使用注解有一個限制,即相同的注解在同一位置只能聲明一次。Java 8引入重復注解,這樣相同的注解在同一地方也可以聲明多次。重復注解機制本身需要用@Repeatable注解。Java 8在編譯器層做了優化,相同注解會以集合的方式保存,因此底層的原理并沒有變化。
(5)擴展注解的支持
Java 8擴展了注解的上下文,幾乎可以為任何東西添加注解,包括局部變量、泛型類、父類與接口的實現,連方法的異常也能添加注解。
(6)Optional
Java 8引入Optional類來防止空指針異常,Optional類最先是由Google的Guava項目引入的。Optional類實際上是個容器:它可以保存類型T的值,或者保存null。使用Optional類我們就不用顯式進行空指針檢查了。
(7)Stream流
Stream API是把真正的函數式編程風格引入到Java中。其實簡單來說可以把Stream理解為MapReduce,當然Google的MapReduce的靈感也是來自函數式編程。她其實是一連串支持連續、并行聚集操作的元素。從語法上看,也很像linux的管道、或者鏈式編程,代碼寫起來簡潔明了,非常酷帥!
(8)Date/Time API (JSR 310)
Java 8新的Date-Time API (JSR 310)受Joda-Time的影響,提供了新的java.time包,可以用來替代 java.util.Date和java.util.Calendar。一般會用到Clock、LocaleDate、LocalTime、LocaleDateTime、ZonedDateTime、Duration這些類,對于時間日期的改進還是非常不錯的。
(9)JavaScript引擎Nashorn
Nashorn允許在JVM上開發運行JavaScript應用,允許Java與JavaScript相互調用。
(10)Base64
在Java 8中,Base64編碼成為了Java類庫的標準。Base64類同時還提供了對URL、MIME友好的編碼器與×××。
33.說說lambda的優缺點。
優點:
1. 簡潔。
2. 非常容易并行計算。
3.?可能代表未來的編程趨勢。
4. 結合 hashmap 的 computeIfAbsent 方法,遞歸運算非常快。java有針對遞歸的專門優化。
缺點:
1. 若不用并行計算,很多時候計算速度沒有比傳統的 for 循環快。(并行計算有時需要預熱才顯示出效率優勢,并行計算目前對 Collection 類型支持的好,對其他類型支持的一般)
2. 不容易調試。
3. 若其他程序員沒有學過 lambda 表達式,代碼不容易讓其他語言的程序員看懂。
4. 在 lambda 語句中強制類型轉換貌似不方便,一定要搞清楚到底是 map 還是 mapToDouble 還是 mapToInt
34.一個十進制的數在內存中是怎么存的?
以二進制補碼形式存儲,最高位是符號位,正數的補碼是它的原碼,負數的補碼是它的反碼加1,在求反碼時符號位不變,符號位為1,其他位取反。
35.為啥有時候會出現4.0-3.6=0.40000001這種現象?
2進制的小數無法精確的表達10進制小數,計算機在計算10進制小數的過程中要先轉換為2進制進行計算,這個過程中出現了誤差。
36.什么是值傳遞和引用傳遞?
值傳遞:
方法調用時,實際參數把它的值傳遞給對應的形式參數,函數接收的是原始值的一個copy,此時內存中存在兩個相等的基本類型,即實際參數和形式參數,后面方法中的操作都是對形參這個值的修改,不影響實際參數的值。
引用傳遞:
也稱為傳地址。方法調用時,實際參數的引用(地址,而不是參數的值)被傳遞給方法中相對應的形式參數,函數接收的是原始值的內存地址;
在方法執行中,形參和實參內容相同,指向同一塊內存地址,方法執行中對引用的操作將會影響到實際對象。
37.數組(Array)和列表(ArrayList)有什么區別?什么時候使用Array而不是ArrayList?
Array:它是數組,申明數組的時候就要初始化并確定長度,長度不可變,而且它只能存儲同一類型的數據,比如申明為String類型的數組,那么它只能存儲S聽類型數據
ArrayList:它是一個集合,需要先申明,然后再添加數據,長度是根據內容的多少而改變的,ArrayList可以存放不同類型的數據,在存儲基本類型數據的時候要使用基本數據類型的包裝類
當能確定長度并且數據類型一致的時候就可以用數組,其他時候使用ArrayList
38.你了解大O符號(big-O notation)么?你能給出不同數據結構的例子嗎?
大O符號表示當數據結構的元素增加的時候,算法規模或者性能在最壞場景下有多好。
大O符號也可以用來描述其他行為,比如說內存消耗。因為集合實際上就是一種數據結構,我們一般用大O符號基于時間、性能、內存消耗來選擇最好的實現。
大O符號可以對大量數據的性能給出一個很好的說明
39.Integer 類和 int 的區別
1)、Integer 是 int 包裝類,int 是八大基本數據類型之一(byte,char,short,int,long,float,double,boolean)
2)、Integer 是類,默認值為null,int是基本數據類型,默認值為0;
3)、Integer 表示的是對象,用一個引用指向這個對象,而int是基本數據類型,直接存儲數值。
40.&和&&的區別?
Java中&&和&都是表示與的邏輯運算符,都表示邏輯運輸符and,當兩邊的表達式都為true的時候,整個運算結果才為true,否則為false。
&&的短路功能,當第一個表達式的值為false的時候,則不再計算第二個表達式;&則兩個表達式都執行。
&可以用作位運算符,當&兩邊的表達式不是Boolean類型的時候,&表示按位操作。
41.java中如何跳出多重嵌套循環?
方法一:可以在需要的循環語句前定義一個標號,
然后在里層循環體的代碼中使用帶有標號的break語句,即可跳出外層循環
方法二:可以在需要的循環條件內加入一個boolean類型的判斷,需要的時候將此變量值反轉,再break當前循環即可跳出。
建議:推薦使用方法一,方便靈活,且代碼可讀性好。示例如下:
public static void main(String[] args) {
method1();
method2();
}
/**
* 利用標簽
*/
public static void method1(){
tag:for (int i=0;i<9;i++){
for (int j=0;j<9;j++){
System.out.println(i+"*"+j+"="+i*j);
if (i==8&&j==7){
break tag;
}
}
}
}
/**
* 增加循環條件判斷
*/
public static void method2(){
boolean flag=true;
for (int i=0;i<9&flag;i++){
for (int j=0;j<9;j++){
System.out.println(i+"*"+j+"="+i*j);
if (i==8&&j==7){
flag=false;
break;
}
}
}
}
42.我們在web應用開發過程種經常遇到輸出某種編碼的字符,如iso8859-1等,如何輸出某種編碼的字符串?
public String translate (String str) {
String tempStr = "";
try {
tempStr = new String(str.getBytes("ISO-8859-1"), "GBK");
tempStr = tempStr.trim();
}catch (Exception e) {
System.err.println(e.getMessage());
}
return tempStr;
}
44.你能比較一下java和JavaScript嗎?
java:面向對象;需要編譯,再進行運行;強類型.
javascript:基于對象和事件驅動;解釋型語言;弱類型!
45.簡述正則表達式及用途?
在編寫處理字符串的程序時,經常會有查找符合某些復雜規則的字符串的需要。正則表達式就是用于描述這些規則的工具。換句話說,正則表達式就是記錄文本規則的代碼。
46.java中是如何支持正則表達式操作的?
Java中的String類提供了支持正則表達式操作的方法,包括:matches()、replaceAll()、replaceFirst()、split()。此外,Java中可以用Pattern類表示正則表達式對象,它提供了豐富的API進行各種正則表達式操作,例如:
面試題: - 如果要從字符串中截取第一個英文左括號之前的字符串,例如:北京市(朝陽區)(西城區)(海淀區),截取結果為:北京市,那么正則表達式怎么寫?
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExpTest {
public static void main(String[] args) {
String str = "北京市(朝陽區)(西城區)(海淀區)";
Pattern p = Pattern.compile(".*?(?=\\()");
Matcher m = p.matcher(str);
if(m.find()) {
System.out.println(m.group());
}
}
}
47.請你說說java和php的區別?
PHP暫時還不支持像Java那樣JIT運行時編譯熱點代碼,但是PHP具有opcache機制,能夠把腳本對應的opcode緩存在內存,PHP7中還支持配置opcache.file_cache導出opcode到文件.第三方的Facebook HHVM也支持JIT.另外PHP官方基于LLVM圍繞opcache機制構建的Zend JIT分支也正在開發測試中.在php-src/Zend/bench.php測試顯示,PHP JIT分支速度是PHP 5.4的10倍. PHP的庫函數用C實現,而Java核心運行時類庫(jdk/jre/lib/rt.jar,大于60MB)用Java編寫(jdk/src.zip), 所以Java應用運行的時候,用戶編寫的代碼以及引用的類庫和框架都要在JVM上解釋執行.
Java的HotSpot機制,直到有方法被執行10000次才會觸發JIT編譯, 在此之前運行在解釋模式下,以避免出現JIT編譯花費的時間比方法解釋執行消耗的時間還要多的情況. PHP內置模板引擎,自身就是模板語言.而Java Web需要使用JSP容器如Tomcat或第三方模板引擎. PHP也可以運行在多線程模式下,比如Apache的event MPM和Facebook的HHVM都是多線程架構.不管是多進程還是多線程的PHP Web運行模式,都不需要PHP開發者關心和控制,也就是說PHP開發者不需要寫代碼參與進程和線程的管理,這些都由PHP-FPM/HHVM/Apache實現.PHP-FPM進程管理和并發實現并不需要PHP開發者關心,而Java多線程編程需要Java開發者編碼參與.PHP一個worker進程崩潰,master進程會自動新建一個新的worker進程,并不會導致PHP服務崩潰.而Java多線程編程稍有不慎(比如沒有捕獲異常)就會導致JVM崩潰退出.對于PHP-FPM和Apache MOD_PHP來說,服務進程常駐內存,但一次請求釋放一次資源,這種內存釋放非常徹底. PHP基于引用計數的GC甚至都還沒發揮作用程序就已經結束了。
48.介紹一下Syncronized鎖,如果用這個關鍵字修飾一個靜態方法,鎖住了什么?如果修飾了成員方法,鎖住了什么?
在synchronized里面,包含有三種常見的鎖狀態:
對于普通的同步方法:
鎖是當前的對象
對于靜態函數的同步方法:
鎖是指引用當前類的class對象
對于同步方法塊的內容:
鎖是指Synchonized括號里配置的對象
49.介紹一下volatile?
volatile作為java中的關鍵詞之一,用以聲明變量的值可能隨時會別的線程修改,使用volatile修飾的變量會強制將修改的值立即寫入主存,主存中值的更新會使緩存中的值失效(非volatile變量不具備這樣的特性,非volatile變量的值會被緩存,線程A更新了這個值,線程B讀取這個變量的值時可能讀到的并不是是線程A更新后的值)。volatile會禁止指令重排 volatile具有可見性、有序性,不具備原子性。 注意,volatile不具備原子性,這是volatile與java中的synchronized、java.util.concurrent.locks.Lock最大的功能差異。
50.說一下sychronized和lock?
1)來源:
lock是一個接口,而synchronized是java的一個關鍵字,synchronized是內置的語言實現;
2)異常是否釋放鎖:
synchronized在發生異常時候會自動釋放占有的鎖,因此不會出現死鎖;而lock發生異常時候,不會主動釋放占有的鎖,必須手動unlock來釋放鎖,可能引起死鎖的發生。(所以最好將同步代碼塊用try catch包起來,finally中寫入unlock,避免死鎖的發生。)
3)是否響應中斷
lock等待鎖過程中可以用interrupt來中斷等待,而synchronized只能等待鎖的釋放,不能響應中斷;
4)是否知道獲取鎖
Lock可以通過trylock來知道有沒有獲取鎖,而synchronized不能;
5)Lock可以提高多個線程進行讀操作的效率。(可以通過readwritelock實現讀寫分離)
6)在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優于synchronized。所以說,在具體使用時要根據適當情況選擇。
7)synchronized使用Object對象本身的wait 、notify、notifyAll調度機制,而Lock可以使用Condition進行線程之間的調度,
51.講一講java里面的final關鍵字怎么用?
在java中,final的含義在不同的場景下有細微的差別,但總體上來說,它指的是“這是不可變的”。下面,我們來講final的四種主要用法。
1)修飾數據
在編寫程序時,我們經常需要說明一個數據是不可變的,我們稱為常量。在java中,用final關鍵字修飾的變量,只能進行一次賦值操作,并且在生存期內不可以改變它的值。更重要的是,final會告訴編譯器,這個數據是不會修改的,那么編譯器就可能會在編譯時期就對該數據進行替換甚至執行計算,這樣可以對我們的程序起到一點優化。不過在針對基本類型和引用類型時,final關鍵字的效果存在細微差別。
2)修飾方法參數
前面我們可以看到,如果變量是我們自己創建的,那么使用final修飾表示我們只會給它賦值一次且不會改變變量的值。那么如果變量是作為參數傳入的,我們怎么保證它的值不會改變呢?這就用到了final的第二種用法,即在我們編寫方法時,可以在參數前面添加final關鍵字,它表示在整個方法中,我們不會(實際上是不能)改變參數的值。
3)修飾方法
第三種方式,即用final關鍵字修飾方法,它表示該方法不能被覆蓋。這種使用方式主要是從設計的角度考慮,即明確告訴其他可能會繼承該類的程序員,不希望他們去覆蓋這個方法。這種方式我們很容易理解,然而,關于private和final關鍵字還有一點聯系,這就是類中所有的private方法都隱式地指定為是final的,由于無法在類外使用private方法,所以也就無法覆蓋它。
4)修飾類
了解了final關鍵字的其他用法,我們很容易可以想到使用final關鍵字修飾類的作用,那就是用final修飾的類是無法被繼承的。
52.wait方法底層原理?
導致當前線程等待,直到該對象的notify或notifyAll被執行。換句話說,這個方法行為效果完全與簡單調用wait(0)一樣。當前線程必須擁有對象監視器。線程釋放對象監視器的所有權,等待直到另一個線程通過調用notify或notifyAll來通知等待對象監視器的線程們并喚醒。然后,當前線程等待重新獲取對象監視器并繼續執行。因為在一個參數的版本中,中斷與偽喚醒是可能的,這個方法應該通常在一個循環中使用:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
該方法必須同步執行的,否則會拋出IllegalMonitorStateException。
53.java有哪些特性,舉個多態的例子。
java有3個特性:繼承、多態、封裝。
多態的定義:指允許不同類的對象對同一消息做出響應,即同一消息可以根據發送對象的不同而采用多種不同的行為方式。
比如有動物(Animal)之(Class),而且由動物繼承出類別雞(Chicken)和類別狗(Dog),并對同一源自類別動物(父類別)之一消息有不同、的響應,如類別動物有“叫()”之動作,而類別雞會“啼叫()”,類別狗則會“吠叫()”,則稱之為多態。。
54.為啥String不可變?
關于為什么String對象不可變,可以看看它的設計源碼。
public final class String
implements java.io.Serializable, Comparable<string>, CharSequence{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0</string>
可以看出String對象本質上就是一個字符數組,這也和數組就是對象相符,也可以解釋了String.charAt()等方法的原理。value[]就是這個字符數組,offset是在數組中的起始位置,count是字符數組的長度即字符串的長度,而hash是這個String對象的hash值緩存。value[],offset和count這三個變量都是private而且沒有setter方法,這也是String對象不可變的本質原因。
55.類和對象的區別?
面向對象的編程思想力圖在程序中對事物的描述與該事物在現實中的形態保持一致。為了做到這一點,面向對象的思想中提出兩個概念,即類和對象。其中,類是對某一類事物的抽象描述,而對象用于表示現實中該類事物的個體。對象是對客觀事物的抽象,類是對對象的抽象。類是一種抽象的數據類型。
它們的關系是,對象是類的實例,類是對象的模板。對象是通過new className產生的,用來調用類的方法;類的構造方法
56.重載和重寫的區別?相同參數不同返回值能重載嗎?
方法重載是指同一個類中的多個方法具有相同的名字,但這些方法具有不同的參數列表,即參數的數量或參數類型不能完全相同
方法重寫是存在子父類之間的,子類定義的方法與父類中的方法具有相同的方法名字,相同的參數表和相同的返回類型
不能重載
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。