面向對象
面向對象編程:拿東西過來做對應的事情
特征:
-
封裝:對象代表什么,就要封裝對應的數據,并提供數據對應的行為
-
繼承:Java中提供一個關鍵字extends,用這個關鍵字可以讓一個類和另一個類建立起繼承關系,可以把子類中重復代碼抽取到父類中,提高代碼復用性。子類可以在父類基礎上增加其他功能,使子類更強大
-
多態:同類型的對象表現出不同形態。前提是有繼承關系,有父類引用指向子類對象,有方法重寫
方法重載和重寫的區別
方法重載:用于一個類中,通過不同的參數列表實現相同方法名的不同功能。
例如:計算器類中,通過處理不同類型的參數或不同數量的參數,實現兩個整數相加、兩個浮點數相加,或者多個數相加,方法名都為add
方法重寫:主要用于子類和父類之間,通過重寫父類的方法實現多態性。
例如:有一個動物類,有一個叫聲的方法,不同子類(貓或者狗)分別實現"汪汪汪"和"喵喵喵"的叫聲,通過動物類調用方法時,根據實際對象的類型發出不同的聲音
接口與抽象類的區別
接口:不能包含具體實現代碼,只能聲明方法和變量,使用interface關鍵字定義。類通過implements關鍵字實現接口時,必須實現接口中聲明的所有抽象方法
抽象類:不能被實例化的類,它可以包含抽象方法(沒有具體實現的方法)和具體方法。使用abstract關鍵字定義,類通過extends關鍵字繼承抽象類,可以選擇性實現抽象類中的抽象方法,但必須實現所有未實現的抽象方法才能實例化
深拷貝和淺拷貝
淺拷貝:只會拷貝基本數據類型的值,以及實例對象的引用地址,并不會復制一份引用地址所指的對象,也就是內部的類屬性指向是同一個對象
深拷貝:既拷貝基本數據類型的值,也會針對實例對象的引用地址所指向的對象進行復制,也就是說內部的類執行指向的不是同一個對象
sleep和wait的區別
-
sleep:是thread類的靜態方法,用于暫停當前線程的執行。作用是讓當前線程暫停指定的時間,在此期間線程不會占用CPU資源
-
wait:是object類的方法,用于讓當前線程暫停執行,直到其他線程調用該對象的notify或者notifyAll方法,作用是讓當前線程暫停執行,并釋放當前對象的鎖(必須在同步上下文中調用),直到其他線程調用該對象的notify或者notifyAll方法
同步上下文
通常與synchronized關鍵字相關,用于定義一個代碼區域,該區域內的代碼在執行時候需要獲取特定的鎖(對象鎖或類鎖),在同步上下文中,線程必須先獲取鎖,才能執行該區域內的代碼
什么是自動拆裝箱
基本數據類型不具備對象的特征,不能調用方法
裝箱:將基本類型轉換成包裝類對象
拆箱:將包裝類對象轉換為基本類型的值
int和Integer區別
-
Integer是int的包裝類,int是Java的基本數據類型
-
Integer變量必須實例化后才能使用
-
Integer實際是對象的引用,new時實際上是生成一個指針指向此對象,Int是直接存儲數據值
-
Integer默認值是null,int是0
==和equals區別
-
==是一個比較運算符,用于比較兩個變量的值是否相等,可以用于比較基本數據類型和引用類型
-
equals用于比較兩個對象的內容是否相等,主要用于引用類型的對象。如果沒重寫比較的是地址值,如果重寫了比較的是對象中屬性的內容
String buffer 和String builder的區別
兩者中的方法和功能完全是等價的
String buffer 中方法大多采用了synchronized關鍵字進行修飾,是線程安全的
在單線程程序下,String builder效率更快,因為他不需要加鎖,不具備多線程安全
final finally finalize
-
final:修飾類意味著不能再派生新的子類,即不能被繼承。修飾變量時,該變量使用中不被改變,必須在聲明時給定初值,在引用中只能讀取不可修改,即為常量。修飾方法時,只能使用,不能在子類中被重寫
-
finally:在try...catch代碼塊后面構造最終執行代碼塊,只要JVM不關閉,里面代碼都能執行,可以把釋放外部資源的代碼寫在其中
-
finalize:這個方法是由垃圾收集器在銷毀對象時調用的,通過重寫方法可以整理系統資源或執行其他清理工作
ArrayList和LinkList區別
-
ArrayList:基于動態數組實現,數組大小可以根據需要動態擴展。可以通過索引隨機訪問元素,但插入和刪除操作需要移動大量元素
-
LinkedList:基于雙向鏈表實現,每個節點包含數據部分和指向前后節的指針,提供高效的插入和刪除操作,只需要修改指針,但訪問效率低,需要遍歷鏈表
HashMap底層是數組+鏈表+紅黑樹,為什么要用這幾類結構
HashMap提供高效的鍵值對存儲和檢索功能。為了在各種場景下都能提供高效的性能,同時平衡時間和空間復雜度
數組:用于存儲哈希表的"桶"(bucket),支持通過索引進行快速訪問,通過哈希函數計算鍵的哈希值,然后將哈希值映射到數組的某個索引位置,可以直接訪問對應的桶。數組在內存中是連續存儲的,使得緩存命中率極高,進一步提升性能。數組大小是固定的,但可以通過動態擴展來適應更多的鍵值對。當數組的負載因子達到一定閾值時,數組會擴容并重新哈希所有鍵值對
鏈表:用于解決哈希沖突,當多個鍵的哈希值映射到同一個數組索引時,這些鍵值對會被存儲在同一個桶中,形成一個鏈表。鏈表長度可以動態變化,不需要預先分配固定大小的空間,使得HashMap在處理大量數據時更加靈活
紅黑樹:鏈表長度超過一定閾值(默認為8),鏈表會轉換為紅黑樹。在最壞情況下,鏈表長度可能很長,導致查找、插入、刪除操作時間復雜度退化為O(n)。紅黑樹操作時間復雜度為O(log n)。紅黑樹在插入和刪除節點時會自動調整樹的結構,以保持平衡
HashMap和HashTable區別
HashMap:不是線程安全的,如果多個線程同時對其進行寫操作,可能會導致數據不一致或運行時異常。允許一個鍵為null,也允許多個值為null。默認初始化容量為16,默認負載因子為0.75。當實際大小超過容量*負載因子時,會觸發擴容。
HashTable:是線程安全的,性能在高并發場景下可能會受到影響,因為每次操作都需要獲取鎖。容量擴展機制比較簡單,每次擴容時會重新計算所有鍵的哈希值,性能開銷較大。不允許鍵或值為null,嘗試插入會拋出異常。默認初始化容量為11,默認負載因子為0.75。
線程創建方式
1.繼承Thread類創建線程
package untitled.MyThread;
?
public class MyThread extends Thread{public void run(){System.out.println("Thread is running");}
}
2.實現Runnable接口創建線程
package untitled.MyThread;
?
public class MyThread implements Runnable{
?@Overridepublic void run() {Thread t=Thread.currentThread();System.out.println("線程名稱:"+t.getName());}
}
3.使用Callable和Future創建線程 有返回值
package untitled.MyThread;
?
import java.util.concurrent.Callable;
?
public class MyThread implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum=0;for(int i=0;i<100;i++){sum+=i;}return sum;}
}
?
package untitled.MyThread;
?
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
?
public class test {public static void main(String[] args) {MyThread t=new MyThread();FutureTask<Integer> task=new FutureTask<>(t);Thread ?t1=new Thread(task);t1.start();Integer res= null;try {res = task.get();} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}System.out.println(res);
?}
}
線程的轉換狀態
-
新建狀態(New) :線程對象被創建后,就進入了新建狀態。例如,Thread thread = new Thread()。
-
就緒狀態(Runnable): 也被稱為“可執行狀態”。線程對象被創建后,其它線程調用了該對象的start()方法,從而來啟動該線程。處于就緒狀態的線程,隨時可能被CPU調度執行。
-
運行狀態(Running):線程獲取CPU權限進行執行。需要注意的是,線程只能從就緒狀態進入到運行狀態。
-
阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。阻塞的情況分三種: 等待阻塞 -- 通過調用線程的wait()方法,讓線程等待某工作的完成。 同步阻塞 -- 線程在獲取synchronized同步鎖失敗(因為鎖被其它線程所占用),它會進入同步阻塞狀態。 其他阻塞 -- 通過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
-
死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命周期。
反射
反射允許對成員變量,成員方法和構造方法的信息進行編程訪問
獲取class對象三種方式
-
Class.foeName("全類名")
-
類名.class
-
對象.getClass
利用反射獲取構造方法
利用反射獲取成員變量
利用反射獲取成員方法
什么是 java 序列化,如何實現 java 序列化
序列化流:可以把Java中的對象寫到本地文件中,也叫對象操作輸出流
public ObjectOutputStream(OutputStream out) 把基本流包裝成高級流
public final void writeobject(Object obj)把對象序列化(寫出)到文件中去
需要讓Javabean類實現Serializable接口
反序列化流:把序列化到本地文件中的對象,讀取到程序中來,也叫對象操作輸入流
public ObjectInputStream(InputStream out)把基本流變成高級流
public Object readObject()把序列化到本地文件中的對象,讀取到程序中來
HTTP常見狀態碼
-
200 OK //客戶端請求成功
-
301 Permanently Moved (永久移除),請求的 URL 已移走。Response 中應該包含一個 Location URL, 說明資源現在所處的位置
-
302 Temporarily Moved 臨時重定向
-
400 Bad Request //客戶端請求有語法錯誤,不能被服務器所理解
-
401 Unauthorized //請求未經授權,這個狀態代碼必須和 WWW-Authenticate 報頭域一起使用
-
403 Forbidden //服務器收到請求,但是拒絕提供服務
-
404 Not Found //請求資源不存在,eg:輸入了錯誤的 URL
-
500 Internal Server Error //服務器發生不可預期的錯誤
-
503 Server Unavailable //服務器當前不能處理客戶端的請求,一段時間后可能恢復正常
GET和POST區別
-
GET 請求的數據會附在URL 之后,以?分割URL 和傳輸數據,參數之間以&相連、
-
POST 把提交的數據則放置在是 HTTP 包的包體中。
-
GET 方式提交的數據最多只能是 1024 字節,理論上POST 沒有限制,可傳較大量的數據。其實這樣說是錯誤的,不準確的:“GET 方式提交的數據最多只能是 1024 字節",因為 GET 是通過 URL 提交數據,那么 GET 可提交的數據量就跟URL 的長度有直接關系了。而實際上,URL 不存在參數上限的問題,HTTP 協議規范沒有對 URL 長度進行限制。這個限制是特定的瀏覽器及服務器對它的限制。IE 對URL 長度的限制是2083 字節(2K+35)。對于其他瀏覽器,如Netscape、FireFox 等,理論上沒有長度限制,其限制取決于操作系統的支持。
-
POST 的安全性要比GET 的安全性高。注意:這里所說的安全性和上面 GET 提到的“安全”不是同個概念。上面“安全”的含義僅僅是不作數據修改,而這里安全的含義是真正的 Security 的含義,比如:通過 GET 提交數據,用戶名和密碼將明文出現在 URL 上,因為(1)登錄頁面有可能被瀏覽器緩存,(2)其他人查看瀏覽器的歷史紀錄,那么別人就可以拿到你的賬號和密碼了,除此之外,使用 GET 提交數據還可能會造成 Cross-site request forgery 攻擊。
-
Get 是向服務器發索取數據的一種請求,而 Post 是向服務器提交數據的一種請求
-
在 FORM(表單)中,Method默認為"GET"
Cookie和Session的區別
-
Cookie 是 web 服務器發送給瀏覽器的一塊信息,瀏覽器會在本地一個文件中給每個 web 服務器存儲 cookie。以后瀏覽器再給特定的 web 服務器發送請求時,同時會發送所有為該服務器存儲的 cookie
-
Session 是存儲在 web 服務器端的一塊信息。session 對象存儲特定用戶會話所需的屬性及配置信息。當用戶在應用程序的 Web 頁之間跳轉時,存儲在 Session 對象中的變量將不會丟失,而是在整個用戶會話中一直存在下去
-
Cookie 和session 的不同點 無論客戶端做怎樣的設置,session 都能夠正常工作。當客戶端禁用 cookie 時將無法使用 cookie
session 能夠存儲任意的Java對象,cookie 只能存儲 String 類型的對象