當前位置:首頁 > 安卓源碼 > 技術博客 >

Java基礎知識的27個點

時間:2019-10-18 00:50 來源:互聯網 作者:源碼搜藏 瀏覽: 收藏 挑錯 推薦 打印

1、JAVA中的幾種基本數據類型是什么,各自占用多少字節。 2、String類能被繼承嗎,為什么 不能。在Java中,只要是被定義為final的類,也可以說是被final修飾的類,就是不能被繼承的。 3、String,Stringbuffer,StringBuilder的區別。 4、ArrayList和LinkedL

1、JAVA中的幾種基本數據類型是什么,各自占用多少字節。

Java基礎知識的27個點

 

2、String類能被繼承嗎,為什么

不能。在Java中,只要是被定義為final的類,也可以說是被final修飾的類,就是不能被繼承的。

3、String,Stringbuffer,StringBuilder的區別。

Java基礎知識的27個點

 

4、ArrayList和LinkedList有什么區別。

簡單的區別: 1.ArrayList是實現了基于動態數組的數據結構,LinkedList基于鏈表的數據結構。 (LinkedList是雙向鏈表,有next也有previous) 2.對于隨機訪問get和set,ArrayList覺得優于LinkedList,因為LinkedList要移動指針。 3.對于新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據。

深度的區別: 1.對ArrayList和LinkedList而言,在列表末尾增加一個元素所花的開銷都是固定的。對ArrayList而言,主要是在內部數組中增加一項,指向所添加的元素,偶爾可能會導致對數組重新進行分配;而對LinkedList而言,這個開銷是統一的,分配一個內部Entry對象。

2.在ArrayList的中間插入或刪除一個元素意味著這個列表中剩余的元素都會被移動;而在LinkedList的中間插入或刪除一個元素的開銷是固定的。

3.LinkedList不支持高效的隨機元素訪問。

4.ArrayList的空間浪費主要體現在在list列表的結尾預留一定的容量空間,而LinkedList的空間花費則體現在它的每一個元素都需要消耗相當的空間

5、講講類的實例化順序。

問題:比如父類靜態數據,構造函數,字段,子類靜態數據,構造函數,字 段,當new的時候,他們的執行順序。

答案: 類加載器實例化時進行的操作步驟(加載–>連接->初始化)。 父類靜態變量、 父類靜態代碼塊、 子類靜態變量、 子類靜態代碼塊、 父類非靜態變量(父類實例成員變量)、 父類構造函數、 子類非靜態變量(子類實例成員變量)、 子類構造函數。

6、用過哪些Map類,都有什么區別。

問題:比如HashMap是線程安全的嗎,并發下使用的Map是什么,他們 內部原理分別是什么,比如存儲方式,hashcode,擴容,默認容量等。 答案: 不安全,并發下使用ConcurrentHashMap。

7、JAVA8的ConcurrentHashMap為什么放棄了分段鎖?

原因:通過 JDK 的源碼和官方文檔看來, 他們認為的棄用分段鎖的原因由以下幾點: 1、加入多個分段鎖浪費內存空間。 2、生產環境中, map 在放入時競爭同一個鎖的概率非常小,分段鎖反而會造成更新等操作的長時間等待。 3、為了提高 GC 的效率

既然棄用了分段鎖, 那么一定由新的線程安全方案, 我們來看看源碼是怎么解決線程安全的呢?CAS

首先通過 hash 找到對應鏈表過后, 查看是否是第一個object, 如果是, 直接用cas原則插入,無需加鎖,然后如果不是鏈表第一個object, 則直接用鏈表第一個object加鎖,這里加的鎖是synchronized,雖然效率不如 ReentrantLock, 但節約了空間,這里會一直用第一個object為鎖, 直到重新計算map大小, 比如擴容或者操作了第一個object為止。

8、ConcurrentHashMap(JDK1.8)為什么要使用synchronized而不是如ReentranLock這樣的可重入鎖?

可以從下面幾個方面講述: 鎖的粒度 首先鎖的粒度并沒有變粗,甚至變得更細了。每當擴容一次,ConcurrentHashMap的并發度就擴大一倍。 Hash沖突 JDK1.7中,ConcurrentHashMap從過二次hash的方式(Segment -> HashEntry)能夠快速的找到查找的元素。在1.8中通過鏈表加紅黑樹的形式彌補了put、get時的性能差距。 擴容 JDK1.8中,在ConcurrentHashmap進行擴容時,其他線程可以通過檢測數組中的節點決定是否對這條鏈表(紅黑樹)進行擴容,減小了擴容的粒度,提高了擴容的效率。

為什么是synchronized,而不是可重入鎖

  1. 減少內存開銷 假設使用可重入鎖來獲得同步支持,那么每個節點都需要通過繼承AQS來獲得同步支持。但并不是每個節點都需要獲得同步支持的,只有鏈表的頭節點(紅黑樹的根節點)需要同步,這無疑帶來了巨大內存浪費。
  2. 獲得JVM的支持 可重入鎖畢竟是API這個級別的,后續的性能優化空間很小。 synchronized則是JVM直接支持的,JVM能夠在運行時作出相應的優化措施:鎖粗化、鎖消除、鎖自旋等等。這就使得synchronized能夠隨著JDK版本的升級而不改動代碼的前提下獲得性能上的提升。

9、有沒有有順序的Map實現類,如果有,他們是怎么保證有序的。

Hashmap和Hashtable 都不是有序的。 TreeMap和LinkedHashmap都是有序的。(TreeMap默認是key升序,LinkedHashmap默認是數據插入順序) TreeMap是基于比較器Comparator來實現有序的。 LinkedHashmap是基于鏈表來實現數據插入有序的。

10、抽象類和接口的區別,類可以繼承多個類么,接口可以繼承多個接口么,類可以實現多個接口 么。

區別: 1、抽象類和接口都不能直接實例化,如果要實例化,抽象類變量必須指向實現所有抽象方法的子類對象,接口變量必須指向實現所有接口方法的類對象。 2、抽象類要被子類繼承,接口要被類實現。 3、接口只能做方法申明,抽象類中可以做方法申明,也可以做方法實現 4、接口里定義的變量只能是公共的靜態的常量,抽象類中的變量是普通變量。 5、抽象類里的抽象方法必須全部被子類所實現,如果子類不能全部實現父類抽象方法,那么該子類只能是抽象類。同樣,一個實現接口的時候,如不能全部實現接口方法,那么該類也只能為抽象類。 6、抽象方法只能申明,不能實現。abstract void abc();不能寫成abstract void abc(){}。 7、抽象類里可以沒有抽象方法 8、如果一個類里有抽象方法,那么這個類只能是抽象類 9、抽象方法要被實現,所以不能是靜態的,也不能是私有的。 10、接口可繼承接口,并可多繼承接口,但類只能單根繼承。

類不能繼承多個類 接口可以繼承多個接口 類可以實現多個接口

11、繼承和聚合的區別在哪。

繼承 指的是一個類繼承另外的一個類的功能,并可以增加它自己的新功能的能力,繼承是類與類或者接口與接口之間最常見的關系;在Java中此類關系通過關鍵字extends明確標識。

Java基礎知識的27個點

 

聚合

聚合體現的是整體與部分、擁有的關系,此時整體與部分之間是可分離的,他們可以具有各自的生命周期;比如計算機與CPU、公司與員工的關系等;

Java基礎知識的27個點

 

12、IO模型有哪些,講講你理解的nio ,他和bio,aio的區別是啥,談談reactor模型。

各IO的區別:

Java基礎知識的27個點

 

reactor是什么?

  1. 事件驅動
  2. 可以處理一個或多個輸入源
  3. 通過Service Handle同步的將輸入事件采用多路復用分發給相應的Request Handler(一個或多個)處理
Java基礎知識的27個點

 

13、反射的原理,反射創建類實例的三種方式是什么。

//創建Class對象的方式一:(對象.getClass()),獲取類中的字節碼文件
Class class1 = p1.getClass();

//創建Class對象的方式二:(類.class:需要輸入一個明確的類,任意一個類型都有一個靜態的class屬性)
Class class3 = Person.class;

//創建Class對象的方式三:(forName():傳入時只需要以字符串的方式傳入即可)
//通過Class類的一個forName(String className)靜態方法返回一個Class對象,className必須是全路徑名稱;
//Class.forName()有異常:ClassNotFoundException
Class class4 = Class.forName("cn.xbmchina.Person");
 

14、反射中,Class.forName和ClassLoader區別 。

Class.forName(className)方法,內部實際調用的方法是 Class.forName(className,true,classloader); 第2個boolean參數表示類是否需要初始化, Class.forName(className)默認是需要初始化。 一旦初始化,就會觸發目標對象的 static塊代碼執行,static參數也也會被再次初始化。 ClassLoader.loadClass(className)方法,內部實際調用的方法是 ClassLoader.loadClass(className,false); 第2個 boolean參數,表示目標對象是否進行鏈接,false表示不進行鏈接,由上面介紹可以, 不進行鏈接意味著不進行包括初始化等一些列步驟,那么靜態塊和靜態對象就不會得到執行

15、描述動態代理的幾種實現方式,分別說出相應的優缺點。

原理區別:

java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。

而cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,通過修改其字節碼生成子類來處理。

1、如果目標對象實現了接口,默認情況下會采用JDK的動態代理實現AOP 2、如果目標對象實現了接口,可以強制使用CGLIB實現AOP

3、如果目標對象沒有實現了接口,必須采用CGLIB庫,spring會自動在JDK動態代理和CGLIB之間轉換

如何強制使用CGLIB實現AOP? (1)添加CGLIB庫,SPRING_HOME/cglib/*.jar (2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>

JDK動態代理和CGLIB字節碼生成的區別? (1)JDK動態代理只能對實現了接口的類生成代理,而不能針對類 (2)CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法 因為是繼承,所以該類或方法最好不要聲明成final

16、final的用途。

1、被final修飾的類不可以被繼承 2、被final修飾的方法不可以被重寫 3、被final修飾的變量不可以被改變(切記不可變的是變量的引用而非引用指向對象的內容。) 4、被final修飾的方法,JVM會嘗試為之尋求內聯,這對于提升Java的效率是非常重要的。因此,假如能確定方法不會被繼承,那么盡量將方法定義為final的,具體參見運行期優化技術的方法內聯部分 5、被final修飾的常量,在編譯階段會存入調用類的常量池中,具體參見類加載機制最后部分和Java內存區域

17、寫出三種單例模式實現 。

1 餓漢式

public class EagerSingleton {
static {
 System.out.println("EagerSingleton 被加載");
}

//私有化構造方法,限制直接構造,只能調用 getInstance() 方法獲取單例對象
private EagerSingleton(){} 



private static final EagerSingleton eagerSingleton=new EagerSingleton(); // 私有化靜態 final成員,類加載直接生成單例對象,比較占用內存 
public static EagerSingleton getInstance(){ //提供對外的公共api獲取單例對象
 return eagerSingleton;
}

}

總結:餓漢式單例的特點:餓漢式在類創建的同時就實例化一個靜態對象出來,不管之后會不會使用這個單例,都會占據一定的內存,但是相應的,在第一次調用時速度也會更快,因為其資源已經初始化完成。

2 懶漢式

public class LazySingleton {
static {
 System.out.println("LazySingleton 被加載");
}
private LazySingleton(){} //私有化構造方法,限制直接構造,只能調用 getInstance() 方法獲取單例對象
private static LazySingleton lazySingleton=null;//靜態域初始化為null,為的是需要時再創建,避免像餓漢式那樣占用內存
public static LazySingleton getInstance(){//提供對外的公共api獲取單例對象
 if(lazySingleton==null){ 
 synchronized (LazySingleton.class){ //在getInstance中做了兩次null檢查,確保了只有第一次調用單例的時候才會做同步,這樣也是線程安全的,同時避免了每次都同步的性能損耗
 if(lazySingleton==null){
 lazySingleton = new LazySingleton();
 }
 }
 }
 return lazySingleton;
 }
}

總結:有同步鎖的性能消耗

3 靜態內部類實現

public class IoDHSingleton {
static {
System.out.println("IoDHSingleton 被加載");
}
private IoDHSingleton(){} //私有化構造方法,限制直接構造,只能調用 getInstance() 方法獲取單例對象
public static IoDHSingleton getInstance(){//提供對外的公共api獲取單例對象
//當getInstance方法第一次被調用的時候,它第一次讀取HolderClass.ioDHSingleton,內部類HolderClass類得到初始化;
//而這個類在裝載并被初始化的時候,會初始化它的靜態域,從而創ioDHSingleton 的實例,由于是靜態的域,因此只會在虛擬機裝載類的時候初始化一次,并由虛擬機來保證它的線程安全性。
 return HolderClass.ioDHSingleton; 
}
 private static class HolderClass{
 static {
 System.out.println("HolderClass 被加載");
 }
 private static IoDHSingleton ioDHSingleton = new IoDHSingleton();
 }
 // 防止反序列化獲取多個對象的漏洞 
 private Object readResolve() throws ObjectStreamException { 
 return HolderClass.ioDHSingleton; 
 } 
}

這個模式的優勢在于,getInstance方法并沒有被同步,并且只是執行一個域的訪問,因此延遲初始化并沒有增加任何訪問成本。

考慮反射: 由于在調用 SingletonHolder.instance 的時候,才會對單例進行初始化,而且通過反射,是不能從外部類獲取內部類的屬性的。 所以這種形式,很好的避免了反射入侵。 考慮多線程: 由于靜態內部類的特性,只有在其被第一次引用的時候才會被加載,所以可以保證其線程安全性。 總結: 優勢:兼顧了懶漢模式的內存優化(使用時才初始化)以及餓漢模式的安全性(不會被反射入侵)。 劣勢:需要兩個類去做到這一點,雖然不會創建靜態內部類的對象,但是其 Class 對象還是會被創建,而且是屬于永久帶的對象。

18、如何在父類中為子類自動完成所有的hashcode和equals實現?這么做有何優劣。

19、請結合OO設計理念,談談訪問修飾符public、private、protected、default在應用設計中的作用。

訪問修飾符,主要標示修飾塊的作用域,方便隔離防護。

public: Java語言中訪問限制最寬的修飾符,一般稱之為“公共的”。被其修飾的類、屬性以及方法不僅可以跨類訪問,而且允許跨包(package)訪問。

private: Java語言中對訪問權限限制的最窄的修飾符,一般稱之為“私有的”。被其修飾的類、屬性以及方法只能被該類的對象訪問,其子類不能訪問,更不能允許跨包訪問

protect: 介于public 和 private 之間的一種訪問修飾符,一般稱之為“保護形”。被其修飾的類、屬性以及方法只能被類本身的方法及子類訪問,即使子類在不同的包中也可以訪問。

default:即不加任何訪問修飾符,通常稱為“默認訪問模式“。該模式下,只允許在同一個包中進行訪問。

20、深拷貝和淺拷貝區別。

淺拷貝(Shallow Copy):

①對于數據類型是基本數據類型的成員變量,淺拷貝會直接進行值傳遞,也就是將該屬性值復制一份給新的對象。因為是兩份不同的數據,所以對其中一個對象的該成員變量值進行修改,不會影響另一個對象拷貝得到的數據。 ②對于數據類型是引用數據類型的成員變量,比如說成員變量是某個數組、某個類的對象等,那么淺拷貝會進行引用傳遞,也就是只是將該成員變量的引用值(內存地址)復制一份給新的對象。因為實際上兩個對象的該成員變量都指向同一個實例。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。

深拷貝:

首先介紹對象圖的概念。設想一下,一個類有一個對象,其成員變量中又有一個對象,該對象指向另一個對象,另一個對象又指向另一個對象,直到一個確定的實例。這就形成了對象圖。那么,對于深拷貝來說,不僅要復制對象的所有基本數據類型的成員變量值,還要為所有引用數據類型的成員變量申請存儲空間,并復制每個引用數據類型成員變量所引用的對象,直到該對象可達的所有對象。也就是說,對象進行深拷貝要對整個對象圖進行拷貝!

簡單地說,深拷貝對引用數據類型的成員變量的對象圖中所有的對象都開辟了內存空間;而淺拷貝只是傳遞地址指向,新的對象并沒有對引用數據類型創建內存空間。

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

數組和鏈表的區別: 1、從邏輯結構角度來看: 數組必須事先定義固定的長度(元素個數),不能適應數據動態地增減的情況。當數據增加時,可能超出原先定義的元素個數;當數據減少時,造成內存浪費。 鏈表動態地進行存儲分配,可以適應數據動態地增減的情況,且可以方便地插入、刪除數據項。(數組中插入、刪除數據項時,需要移動其它數據項) 2、數組元素在棧區,鏈表元素在堆區; 3、從內存存儲角度來看: (靜態)數組從棧中分配空間, 對于程序員方便快速,但自由度小。 鏈表從堆中分配空間, 自由度大但申請管理比較麻煩。 數組利用下標定位,時間復雜度為O(1),鏈表定位元素時間復雜度O(n); 數組插入或刪除元素的時間復雜度O(n),鏈表的時間復雜度O(1)。

22、error和exception的區別,CheckedException,RuntimeException的區別。

Java基礎知識的27個點

 

23、在自己的代碼中,如果創建一個java.lang.String類,這個類是否可以被類加載器加載?為什么。

Java基礎知識的27個點

 

加載過程中會先檢查類是否被已加載,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個classloader已加載就視為已加載此類,保證此類只所有ClassLoader加載一次。而加載的順序是自頂向下,也就是說當發現這個類沒有的時候會先去讓自己的父類去加載,父類沒有再讓兒子去加載,那么在這個例子中我們自己寫的String應該是被Bootstrap ClassLoader加載了,所以App ClassLoader就不會再去加載我們寫的String類了,導致我們寫的String類是沒有被加載的。

24、說一說你對java.lang.Object對象中hashCode和equals方法的理解。在什么場景下需要重新實現這兩個方法。

對于equals()與hashcode(),比較通用的規則: ①兩個obj,如果equals()相等,hashCode()一定相等 ②兩個obj,如果hashCode()相等,equals()不一定相等

25、在jdk1.5中,引入了泛型,泛型的存在是用來解決什么問題。

面向對象的轉型只會發生在具有繼承關系的父子類中(接口也是繼承的一種) 向上轉型:其核心目的在于參數的統一上,根本不需要強制類型轉換。 向下轉型:是為了操作子類定義的特殊功能,需要強制類型轉換,可是現在存在的問題是:向下轉型其實是一種非常不安全的操作,以為編譯的時候,程序不會報錯,而在運行的時候會報錯,這就是傳說中的—迷之報錯。

不過呢,在JDK1.5之后,新增加了泛型的技術,這就將上述向下轉型的問題消滅在了萌芽之中。 泛型的核心意義在于:類在進行定義的時候可以使用一個標記,此標記就表示類中屬性或者方法以及參數的類型,標記在使用的時候,才會去動態的設置類型。

26、Java中的HashSet內部是如何工作的。

HashSet 的內部采用 HashMap來實現。由于 Map 需要 key 和 value,所以HashSet中所有 key 的都有一個默認 value。類似于 HashMap,HashSet 不允許重復的 key,只允許有一個null key,意思就是 HashSet 中只允許存儲一個 null 對象。

27、什么是序列化,怎么序列化,為什么序列化,反序列化會遇到什么問題,如何解決。

什么是序列化? 序列化:把對象轉換為字節序列的過程稱為對象的序列化。 反序列化:把字節序列恢復為對象的過程稱為對象的反序列化

什么情況下需要序列化? 當你想把的內存中的對象狀態保存到一個文件中或者數據庫中時候; 當你想用套接字在網絡上傳送對象的時候; 當你想通過RMI傳輸對象的時候;

如何實現序列化? 實現Serializable接口即可

注意事項: transient 修飾的屬性,是不會被序列化的 靜態static的屬性,他不序列化。 實現這個Serializable 接口的時候,一定要給這個 serialVersionUID 賦值

關于 serialVersionUID 的描述: 序列化運行時使用一個稱為 serialVersionUID 的版本號與每個可序列化類相關聯,該序列號在反序列化過程中用于驗證序列化對象的發送者和接收者是否為該對象加載了與序列化兼容的類。如果接收者加載的該對象的類的 serialVersionUID 與對應的發送者的類的版本號不同,則反序列化將會導致 InvalidClassException。可序列化類可以通過聲明名為 “serialVersionUID” 的字段(該字段必須是靜態 (static)、最終 (final) 的 long 型字段)顯式聲明其自己的 serialVersionUID

Java基礎知識的27個點 轉載http://www.glgbknaa.icu/appboke/44076.html

技術博客閱讀排行

最新文章

内蒙古十一选五助手下载