Java基礎知識(牛客刷題)記錄..(持續輸出中)

Kingwe19發表於2020-10-15

1. Java 重寫(Override)與過載(Overload)

  • 重寫(Override)

重寫是子類對父類的允許訪問的方法的實現過程進行重新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!
重寫的好處在於子類可以根據需要,定義特定於自己的行為。 也就是說子類能夠根據需要實現父類的方法。
重寫方法不能丟擲新的檢查異常或者比被重寫方法申明更加寬泛的異常。例如: 父類的一個方法申明瞭一個檢查異常 IOException,但是在重寫這個方法的時候不能丟擲 Exception 異常,因為 Exception 是 IOException 的父類,只能丟擲 IOException 的子類異常。

  • 過載(Overload)

過載(overloading) 是在一個類裡面,方法名字相同,而引數不同。返回型別可以相同也可以不同。
每個過載的方法(或者建構函式)都必須有一個獨一無二的引數型別列表。
最常用的地方就是構造器的過載。

過載規則:

  • 被過載的方法必須改變引數列表(引數個數或型別不一樣);
  • 被過載的方法可以改變返回型別;
  • 被過載的方法可以改變訪問修飾符;
  • 被過載的方法可以宣告新的或更廣的檢查異常;
  • 方法能夠在同一個類中或者在一個子類中被過載。
  • 無法以返回值型別作為過載函式的區分標準。

2. 正規表示式

大寫表示“非”,d表示digit數字。非數字就是\D, w表示word,非單詞就是\W

3. 抽象類(abstract)和介面

抽象類

  1. 最好不要有private因為私有和抽象放在一起,子類如果想重寫父類的私有方法根本繼承不過來,也就無法重寫
  2. 抽象類中可以有非抽象方法,甚至抽象類中可以都是非抽象的方法(但是後者沒有啥意義)
  3. 抽象類中是可以定義靜態方法的,但是不可以定義靜態抽象方法

介面

  1. 介面允許定義成員,但必須是常量,因為定義的變數,在編譯的時候都會預設加上public static final。
  2. 在介面中的方法,永遠都被public來修飾。
  3. 介面中定義的方法都需要有實現類來實現,如果實現類不能實現介面中的所有方法則實現類定義為抽象類。

比較

  1. 抽象類中可以有靜態方法,介面中也可以有。
  2. 抽象類和介面類無法例項化(忽略匿名內部類),任何編譯器中直接使用new會報錯。
  3. 抽象類可以有構造方法,介面中不能有構造方法

4. 類載入器

Java語言系統自帶有三個類載入器:

  • Bootstrap ClassLoader 最頂層的載入類,主要載入核心類庫,%JRE_HOME%\lib下的rt.jar、resources.jar、charsets.jar和class等。另外需要注意的是可以通過啟動jvm時指定-Xbootclasspath和路徑來改變Bootstrap ClassLoader的載入目錄。比如java -Xbootclasspath/a:path被指定的檔案追加到預設的bootstrap路徑中。我們可以開啟我的電腦,在上面的目錄下檢視,看看這些jar包是不是存在於這個目錄。
  • Extention ClassLoader 擴充套件的類載入器,載入目錄%JRE_HOME%\lib\ext目錄下的jar包和class檔案。還可以載入-D java.ext.dirs選項指定的目錄。
  • Appclass Loader也稱為SystemAppClass 載入當前應用的classpath的所有類。

       一般對於我們java程式設計師來說,類的載入使用的是雙親委派模型,即當一個類需要載入時,會將類傳給Application ClassLoader,但是Application ClassLoader並不會載入,不管它是否能載入,而是傳給它的"父類" Extension ClassLoader,Extension ClassLoader同樣不會載入,同樣傳給 Bootstrap ClassLoader(注意不是我們常說的那種父類,但是可以這樣理解),這時Bootstrap ClassLoader會判斷它是否能載入,能載入就直接載入了,不能載入就傳給Extension ClassLoader,Extension ClassLoader同樣的判斷是否能載入,能載入就直接載入,不能載入就傳給Application ClassLoader,然後Application ClassLoader也判斷能否載入,如果還是不能載入應該就是報ClassNotFoundException了。這就是雙親委託模型的簡單理解了。
       對於上面的"父類"為什麼要打引號,因為它們並不是真的像java中繼承的關係,而是組合的關係,即在"子類"中存在一個成員變數指向"父類"的引用。

5. Java垃圾回收

垃圾回收

持久代是屬於方法區記憶體的部分,而新生代和老年代都是屬於堆記憶體區域的。

  1. 新生代:(包括:Eden區、Survivor from區、Survivor to區)
  • 所有物件建立在新生代的Eden區,當Eden區滿時會進行一次Minor GC操作,將Eden區進行回收,此時判斷存活的物件會被複制進入Survivor from區(年齡加1),對於大物件直接進入老年代,實際上是為了保證Eden區具有充足的空間可用的一種策略
  • 保證一個Survivor區是空的,新生代Minor GC就是在兩個Survivor區之間相互複製存活物件,直到Survivor區滿為止,對於長期存活的物件直接進入老年代,實際上時對Eden區到Survivor區過度的一種策略,是為了保證Eden區到Survivor區不會頻繁的進行復制一直存活的物件且對Survivor區也能保證不會具有太多的一直佔據的記憶體
  1. 老年代:當Survivor區也滿了之後就通過Minor GC將物件複製到老年代 (在發生MinorGC之前,JVM會判斷之前每次晉升到老年代的平均大小是否大於老年代剩餘空間的大小,若大於則進行full GC) 。老年代也滿了的話,就將觸發Full GC,針對整個堆(包括新生代、老年代、持久代)進行垃圾回收。
  2. 持久代:持久代如果滿了,將觸發Full GC。

6. hashCode()方法和equals()方法

作用:在Java裡都是用來對比兩個物件是否相等一致。

那麼equals()既然已經能實現對比的功能了,為什麼還要hashCode()呢?因為重寫的equals()裡一般比較的比較全面比較複雜,這樣效率就比較低,而利用hashCode()進行對比,則只要生成一個hash值進行比較就可以了,效率很高。
那麼hashCode()既然效率這麼高為什麼還要equals()呢? 因為hashCode()並不是完全可靠,有時候不同的物件他們生成的hashcode也會一樣(生成hash值得公式可能存在的問題),所以hashCode()只能說是大部分時候可靠,並不是絕對可靠,
所以我們可以得出:

  1. equals()相等的兩個物件他們的hashCode()肯定相等,也就是用equals()對比是絕對可靠的。
  2. hashCode()相等的兩個物件他們的equal()不一定相等,也就是hashCode()不是絕對可靠的。

所有對於需要大量並且快速的對比的話如果都用equals()去做顯然效率太低,所以解決方式是,每當需要
對比的時候,首先用hashCode()去對比,如果hashCode()不一樣,則表示這兩個物件肯定不相等(也就是不必再用equal()去再對比了),如果hashCode()相同,此時再對比他們的equals(),如果equals()也相同,則表示這兩個物件是真的相同了,這樣既能大大提高了效率也保證了對比的絕對正確性!

7.集合——List,Set以及Map

轉載請註明出處:
Java集合中List,Set以及Map等集合體系詳解(史上最全)

Map:

Map集合類keyvalue
HashMap允許為null允許為null
TreeMap不允許為null允許為null
ConcurrentMap不允許為null不允許為null
HashTable不允許為null不允許為null

8. Servlet

Servlet的生命週期分為5個階段:載入、建立、初始化、處理客戶請求、解除安裝。

  1. 載入:容器通過類載入器使用servlet類對應的檔案載入servlet
  2. 建立:通過呼叫servlet建構函式建立一個servlet物件
  3. 初始化:呼叫init方法初始化
  4. 處理客戶請求:每當有一個客戶請求,容器會建立一個執行緒來處理客戶請求
  5. 解除安裝:呼叫destroy方法讓servlet自己釋放其佔用的資源

9. java初始化的載入順序為:

父類靜態成員變數 父類靜態程式碼塊 子類靜態成員變數 子類靜態程式碼塊 父類非靜態成員變數,父類非靜態程式碼塊,父類建構函式,子類非靜態成員變數,子類非靜態程式碼塊,子類建構函式

相關文章