JavaSE總結
- 一. 基礎程式設計
-
- 基礎文法(這裡不再概述)
- 面向對象
-
- 類與對象
- 類的結構
- 三大特征
- 權限修飾符
- 接口與抽象類
- 關鍵字的使用與含義
- 異常處理
-
- 異常處理的方式
- 自定義異常類
- 二. 進階程式設計
-
- 多線程
-
- 程式,程序,線程的了解
- 并行與并發
- 建立線程的4種方式
- Thread類
- 線程的同步機制
- 線程的通信
- 常用類
-
- 包裝類
- String類
- StringBuffer,StringBuilder類
- 關于日期時間的API
- 比較器
- 枚舉類
- 注解
- 集合
- IO流
- 泛型
- 網絡程式設計
- 反射
-
- 擷取Class類的執行個體
- 反射的四大應用
- java8新特性
-
- Stream流
一. 基礎程式設計
基礎文法(這裡不再概述)
面向對象
面向對象是JavaSE中的靈魂,進階程式設計中的每一項其實就是拿來一個類,接口等讓你使用,是以面向對象是重中之重。
類與對象
類:對一類事物的描述,是抽象的、概念上的定義
對象:是實際存在的該類事物的每個個體,因而也稱為執行個體(instance)
面向對象程式設計的重點是類的設計
設計類,就是設計類的成員。
二者的關系:對象,是由類new出來的,派生出來的。
面向過程:強調的是功能行為,以函數為最小機關,考慮怎麼做。
面向對象:強調具備了功能的對象,以類/對象為最小機關,考慮誰來做。
面向對象可以想為一個大公司,面向過程可以想為一個小公司,即小公司對于接到的活都是一起辦了,即是一種面向過程的思想;
大公司不能再向小公司一樣對于接到的活所有人一起去解決,那樣太耗費時間了,并且容易亂,這個時候大公司就會将公司分成好幾個部門,
每一個部門專門應對某些事情,這樣即為封裝為類的一種思想,且如果想對一個部門添加一些新功能直接給他加上新的屬性方法即可。
面向對象思想落地實作的規則
- 1.建立類,設計類的成員
- 2.建立類的對象
- 3.通過“對象.屬性”或“對象.方法”調用對象的結構
對象的建立與對象的記憶體解析
典型代碼:
Person p1 = new Person();
Person p2 = new Person();
Person p3 = p1;//沒有新建立一個對象,共用一個堆空間中的對象實體。
說明:
如果建立了一個類的多個對象,則每個對象都獨立的擁有一套類的屬性。(非static的)
意味着:如果我們修改一個對象的屬性a,則不影響另外一個對象屬性a的值。
類的結構
1.屬性
對比:屬性 vs 局部變量
相同點:
-
1.1 定義變量的格式:資料類型 變量名 = 變量值
-
1.2 先聲明,後使用
-
1.3 變量都其對應的作用域
不同點:
-
1.1 在類中聲明的位置的不同
-
1.2 關于權限修飾符的不同
-
1.3 有預設初始化值
2.方法
方法:描述類應該具的功能。
方法的聲明:
權限修飾符 傳回值類型 方法名(形參清單){
方法體
}
3.構造器
構造器的作用:
- 1.建立對象
- 2.初始化對象的資訊
使用說明:
- 1.如果沒顯式的定義類的構造器的話,則系統預設提供一個空參的構造器
- 2.定義構造器的格式:權限修飾符 類名(形參清單){}
- 3.一個類中定義的多個構造器,彼此構成重載
- 4.一旦我們顯式的定義了類的構造器之後,系統就不再提供預設的空參構造器
- 5.一個類中,至少會有一個構造器。
三大特征
1.封裝性
隐藏對象内部的複雜性,隻對外公開簡單的接口。便于外界調用,進而提高系統的可擴充性、可維護性。通俗的說,把該隐藏的隐藏起來,該暴露的暴露出來。這就是封裝性的設計思想。
當我們建立一個類的對象以後,我們可以通過"對象.屬性"的方式,對對象的屬性進行指派。這裡,指派操作要受到屬性的資料類型和存儲範圍的制約。除此之外,沒其他制約條件。但是,在實際問題中,我們往往需要給屬性指派加入額外的限制條件。這個條件就不能在屬性聲明時展現,我們隻能通過方法進行限制條件的添加。(比如:setLegs()同時,我們需要避免使用者再使用"對象.屬性"的方式對屬性進行指派。則需要将屬性聲明為私有的(private).
展現一:将類的屬性xxx私化(private),同時,提供公共的(public)方法來擷取(getXxx)和設定(setXxx)此屬性的值
private double radius;
public void setRadius(double radius){
this.radius = radius;
}
public double getRadius(){
return radius;
}
展現二:不對外暴露的私有的方法
展現三:單例模式(将構造器私有化)
展現四:如果不希望類在包外被調用,可以将類設定為預設的。
2.繼承性
1.為什麼要有類的繼承性?
- ① 減少了代碼的備援,提高了代碼的複用性
- ② 便于功能的擴充
- ③ 為之後多态性的使用,提供了前提
2.繼承性的格式:
class A extends B{}
A:子類、派生類、subclass
B:父類、超類、基類、superclass
3.子類繼承父類以後有哪些不同?
展現:一旦子類A繼承父類B以後,子類A中就擷取了父類B中聲明的所有的屬性和方法。
特别的,父類中聲明為private的屬性或方法,子類繼承父類以後,仍然認為擷取了父類中私的結構。隻因為封裝性的影響,使得子類不能直接調用父類的結構而已。
子類繼承父類以後,還可以聲明自己特有的屬性或方法:實作功能的拓展。
子類和父類的關系,不同于子集和集合的關系。
extends:延展、擴充
4.Java中繼承性的說明
- 1.一個類可以被多個子類繼承。
- 2.Java中類的單繼承性:一個類隻能有一個父類
- 3.子父類是相對的概念。
- 4.子類直接繼承的父類,稱為:直接父類。間接繼承的父類稱為:間接父類
- 5.子類繼承父類以後,就擷取了直接父類以及所間接父類中聲明的屬性和方法
5.Object類的了解
- 如果我們沒顯式的聲明一個類的父類的話,則此類繼承于java.lang.Object類
- 所的java類(除java.lang.Object類之外都直接或間接的繼承于java.lang.Object類
- 意味着,所的java類具有java.lang.Object類聲明的功能。
3.多态性
1.多态性的了解:可以了解為一個事物的多種形态。
2.何為多态性:
對象的多态性:父類的引用指向子類的對象(或子類的對象賦給父類的引用)
3.舉例:
Person p = new Man();
Object obj = new Date();
即父類的引用指向子類的對象!
4.多态的應用
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM38FdsYkRGZkRG9lcvx2bjxiNx8VZ6l2cs0TUIFmbs1mWmRWbihmVzolb1cVWwh2MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLhZmNjFDZwE2Y0IDZyMWOilzM1QTMjJTYkR2N2UGMzMzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
即我們可以了解為對于方法的輸入類型有若幹類型時,若其滿足有同一父類,我們可以使用其父類來做參數類型,即用其父類的引用來指向子類的對象。
而同時由于我們是先用其父類來“代表”了一下其各個子類,在方法内部的進行對輸入類型的方法調用時,由于我們是拿到的父類,是以這裡必然是不能用其各個子類的方法的;
并且我們是拿到的父類,但是最終參數輸入後我們是用父類的引用來指向子類,是以使用的父類的方法換成了子類重寫的方法。
即你可以了解為通過多态,将父類的引用指向了子類的對象,即你相當于就是拿到了子類對象自己。但是由于你開始時的“容器”是隻按照了父類的形狀等設定的,是以你拿到的子類對象想要真正使用時,即要裝進“容器”時發現裝不完,即他作為子類多出來的别的功能放不進去的,是以又被舍棄了,是以拿到的就還是父類本身,不過其方法若被重寫的話是會保留的,因為其将原來父類的覆寫了,是以能放進“容器”中。
總結:
一種代碼呈現多種形态,省去了多種重載方法的設計了;
對象的多态性–對象以多種形态呈現;
5.equals方法其實就是多态性的一個執行個體:
equals方法就是多态性的一個執行個體,若其對每一種引用類型都寫一個equals方法,太過繁雜且邏輯幾乎重複,于是我們使用所有引用類型的祖宗Object類來先作為參數,将此種方法寫好,這樣的話後面可以自行根據輸入的對象類型而調到不同的類型的吃和叫方法,即減少了代碼量。
權限修飾符
Java規定的四種權限修飾符
權限從小到大順序為:private < 預設 < protected < public
具體的修飾範圍:
權限修飾符可用來修飾的結構說明:
4種權限都可以用來修飾類的内部結構:屬性、方法、構造器、内部類
修飾類的話,隻能使用:預設、public
接口與抽象類
接口
1.接口使用interface來定義
2.Java中,接口和類是并列的兩個結構
3.如何定義接口:定義接口中的成員
3.1 JDK7及以前:隻能定義全局常量和抽象方法
全局常量:public static final的.但是書寫時,可以省略不寫
抽象方法:public abstract的
3.2 JDK8:除了定義全局常量和抽象方法之外,還可以定義靜态方法、預設方法
4.接口中不能定義構造器的!意味着接口不可以執行個體化
5.Java開發中,接口通過讓類去實作(implements)的方式來使用.
如果實作類覆寫了接口中的所抽象方法,則此實作類就可以執行個體化
如果實作類沒覆寫接口中所的抽象方法,則此實作類仍為一個抽象類
6.Java類可以實作多個接口 —>彌補了Java單繼承性的局限性
格式:class AA extends BB implements CC,DD,EE
7.接口與接口之間可以繼承,而且可以多繼承
8.接口的具體使用,展現多态性
9.接口,實際上可以看做是一種規範
抽象類與抽象方法
abstract: 抽象的
1.可以用來修飾:類、方法
2.具體的:
abstract修飾類:抽象類
此類不能執行個體化
抽象類中一定有構造器,便于子類執行個體化時調用(涉及:子類對象執行個體化的全過程)
開發中,都會提供抽象類的子類,讓子類對象執行個體化,完成相關的操作 —>抽象的使用前提:繼承性
abstract修飾方法:抽象方法
抽象方法隻方法的聲明,沒方法體
包含抽象方法的類,一定是一個抽象類。反之,抽象類中可以沒有抽象方法的。
若子類重寫了父類中的所的抽象方法後,此子類方可執行個體化
若子類沒重寫父類中的所的抽象方法,則此子類也是一個抽象類,需要使用abstract修飾
3.注意點:
- 1.abstract不能用來修飾:屬性、構造器等結構
- 2.abstract不能用來修飾私方法、靜态方法、final的方法、final的類
關鍵字的使用與含義
1.this
this了解為:目前對象 或 目前正在建立的對象,可以調用的結構:屬性、方法;構造器。
2.package,import
使用package聲明類或接口所屬的包,聲明在源檔案的首行;
在源檔案中顯式的使用import結構導入指定包下的類、接口;
3.super
super 關鍵字可以簡單了解為:父類的。可以用來調用的結構:屬性、方法、構造器。
4.static
static:靜态的
可以用來修飾的結構:主要用來修飾類的内部結構
屬性、方法、代碼塊、内部類
static修飾屬性的其他說明:
① 靜态變量随着類的加載而加載。可以通過"類.靜态變量"的方式進行調用
② 靜态變量的加載要早于對象的建立。
③ 由于類隻會加載一次,則靜态變量在記憶體中也隻會存在一份:存在方法區的靜态域中。
5.final
final:最終的
可以用來修飾:類、方法、變量
用來修飾一個類:此類不能被其他類所繼承。用來修飾方法:表明此方法不可以被重寫。用來修飾變量:此時的"變量"就稱為是一個常量
異常處理
異常處理的方式
異常處理方式一:try-catch-finally
使用說明:
try{
//可能出現異常的代碼
}catch(異常類型1 變量名1){
//處理異常的方式1
}catch(異常類型2 變量名2){
//處理異常的方式2
}catch(異常類型3 變量名3){
//處理異常的方式3
}
....
finally{
//一定會執行的代碼
}
說明:
- finally是可的。
- 使用try将可能出現異常代碼包裝起來,在執行過程中,一旦出現異常,就會生成一個對應異常類的對象,根據此對象的類型,去catch中進行比對
- 一旦try中的異常對象比對到某一個catch時,就進入catch中進行異常的處理。一旦處理完成,就跳出目前的try-catch結構(在沒寫finally的情況。繼續執行其後的代碼
-
catch中的異常類型如果沒子父類關系,則誰聲明在上,誰聲明在下無所謂。
catch中的異常類型如果滿足子父類關系,則要求子類一定聲明在父類的上面。否則報錯
- 常用的異常對象處理的方式: ① String getMessage() ② printStackTrace()
- 在try結構中聲明的變量,再出了try結構以後,就不能再被調用
- try-catch-finally結構可以嵌套
異常處理方式二:
"throws + 異常類型"寫在方法的聲明處。指明此方法執行時,可能會抛出的異常類型。
一旦當方法體執行時,出現異常,仍會在異常代碼處生成一個異常類的對象,此對象滿足throws後異常類型時,就會被抛出。異常代碼後續的代碼,就不再執行!
對比兩種處理方式
try-catch-finally:真正的将異常給處理掉了。
throws的方式隻是将異常抛給了方法的調用者。并沒真正将異常處理掉。
自定義異常類
如何自定義異常類?
- 繼承于現的異常結構:RuntimeException 、Exception
- 提供全局常量:serialVersionUID
- 提供重載的構造器
public class MyException extends Exception{
static final long serialVersionUID = -7034897193246939L;
public MyException(){
}
public MyException(String msg){
super(msg);
}
}
二. 進階程式設計
多線程
程式,程序,線程的了解
-
程式(programm)
概念:是為完成特定任務、用某種語言編寫的一組指令的集合。即指一段靜态的代碼。
-
程序(process)
概念:程式的一次執行過程,或是正在運作的一個程式。
說明:程序作為資源配置設定的機關,系統在運作時會為每個程序配置設定不同的記憶體區域
-
線程(thread)
概念:程序可進一步細化為線程,是一個程式内部的一條執行路徑。
說明:線程作為排程和執行的機關,每個線程擁獨立的運作棧和程式計數器(pc),線程切換的開銷小。
并行與并發
并行與并發的了解
并行:多個CPU同時執行多個任務。比如:多個人同時做不同的事。
并發:一個CPU(采用時間片)同時執行多個任務。比如:秒殺、多個人做同一件事
建立線程的4種方式
方式一:繼承Thread類的方式:
- 建立一個繼承于Thread類的子類
- 重寫Thread類的run() --> 将此線程執行的操作聲明在run()中
- 建立Thread類的子類的對象
- 通過此對象調用start():①啟動目前線程 ② 調用目前線程的run()
方式二:實作Runnable接口的方式:
- 建立一個實作了Runnable接口的類
- 實作類去實作Runnable中的抽象方法:run()
- 建立實作類的對象
- 将此對象作為參數傳遞到Thread類的構造器中,建立Thread類的對象
- 通過Thread類的對象調用start()
新增方式一:實作Callable接口。 — JDK 5.0新增
//1.建立一個實作Callable的實作類
class NumThread implements Callable{
//2.實作call方法,将此線程需要執行的操作聲明在call()中
@Override
public Object call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
if(i % 2 == 0){
System.out.println(i);
sum += i;
}
}
return sum;
}
}
public class ThreadNew {
public static void main(String[] args) {
//3.建立Callable接口實作類的對象
NumThread numThread = new NumThread();
//4.将此Callable接口實作類的對象作為傳遞到FutureTask構造器中,建立FutureTask的對象
FutureTask futureTask = new FutureTask(numThread);
//5.将FutureTask的對象作為參數傳遞到Thread類的構造器中,建立Thread對象,并調用start()
new Thread(futureTask).start();
try {
//6.擷取Callable中call方法的傳回值
//get()傳回值即為FutureTask構造器參數Callable實作類重寫的call()的傳回值。
Object sum = futureTask.get();
System.out.println("總和為:" + sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
新增方式二:使用線程池
class NumberThread implements Runnable{
@Override
public void run() {
for(int i = 0;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}
class NumberThread1 implements Runnable{
@Override
public void run() {
for(int i = 0;i <= 100;i++){
if(i % 2 != 0){
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//1. 提供指定線程數量的線程池
ExecutorService service = Executors.newFixedThreadPool(10);
ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
//設定線程池的屬性
// System.out.println(service.getClass());
// service1.setCorePoolSize(15);
// service1.setKeepAliveTime();
//2.執行指定的線程的操作。需要提供實作Runnable接口或Callable接口實作類的對象
service.execute(new NumberThread());//适合适用于Runnable
service.execute(new NumberThread1());//适合适用于Runnable
// service.submit(Callable callable);//适合使用于Callable
//3.關閉連接配接池
service.shutdown();
}
}
Thread類
Thread類中的常用的方法:
- start():啟動目前線程;調用目前線程的run()
- run(): 通常需要重寫Thread類中的此方法,将建立的線程要執行的操作聲明在此方法中
- currentThread():靜态方法,傳回執行目前代碼的線程
- getName():擷取目前線程的名字
- setName():設定目前線程的名字
- yield():釋放目前cpu的執行權
- join():線上程a中調用線程b的join(),此時線程a就進入阻塞狀态,直到線程b完全執行完以後,線程a才結束阻塞狀态。
- stop():已過時。當執行此方法時,強制結束目前線程。
- sleep(long millitime):讓目前線程“睡眠”指定的millitime毫秒。在指定的millitime毫秒時間内,目前線程是阻塞狀态。
- isAlive():判斷目前線程是否存活
Thread的生命周期
說明:
1.生命周期關注兩個概念:狀态、相應的方法
2.關注:狀态a–>狀态b:哪些方法執行了(回調方法)
某個方法主動調用:狀态a–>狀态b
3.阻塞:臨時狀态,不可以作為最終狀态
死亡:最終狀态。
線程的同步機制
在Java中,我們通過同步機制,來解決線程的安全問題。
方式一:同步代碼塊
synchronized(同步螢幕){
//需要被同步的代碼
}
說明:
1.操作共享資料的代碼,即為需要被同步的代碼。 -->不能包含代碼多了,也不能包含代碼少了。
2.共享資料:多個線程共同操作的變量。比如:ticket就是共享資料。
3.同步螢幕,俗稱:鎖。任何一個類的對象,都可以充當鎖。
要求:多個線程必須要共用同一把鎖。
補充:在實作Runnable接口建立多線程的方式中,我們可以考慮使用this充當同步螢幕。
在繼承Thread類建立多線程的方式中,慎用this充當同步螢幕,考慮使用目前類充當同步螢幕。
方式二:同步方法
如果操作共享資料的代碼完整的聲明在一個方法中,我們不妨将此方法聲明同步的。
關于同步方法的總結:
- 同步方法仍然涉及到同步螢幕,隻是不需要我們顯式的聲明。
-
非靜态的同步方法,同步螢幕是:this
靜态的同步方法,同步螢幕是:目前類本身
方式三:Lock鎖 — JDK5.0新增
面試題:synchronized 與 Lock的異同?
相同:二者都可以解決線程安全問題
不同:synchronized機制在執行完相應的同步代碼以後,自動的釋放同步螢幕
Lock需要手動的啟動同步(lock(),同時結束同步也需要手動的實作(unlock())
使用的優先順序:
Lock —> 同步代碼塊(已經進入了方法體,配置設定了相應資源 ) —> 同步方法(在方法體之外)
線程的通信
1.線程通信涉及到的三個方法:
- wait():一旦執行此方法,目前線程就進入阻塞狀态,并釋放同步螢幕。
- notify():一旦執行此方法,就會喚醒被wait的一個線程。如果有多個線程被wait,就喚醒優先級高的那個。
- notifyAll():一旦執行此方法,就會喚醒所有被wait的線程。
2.說明:
- 1.wait(),notify(),notifyAll()三個方法必須使用在同步代碼塊或同步方法中。
- 2.wait(),notify(),notifyAll()三個方法的調用者必須是同步代碼塊或同步方法中的同步螢幕。
- 否則,會出現IllegalMonitorStateException異常
- 3.wait(),notify(),notifyAll()三個方法是定義在java.lang.Object類中
常用類
包裝類
1.為什麼要有包裝類(或封裝類)
為了使基本資料類型的變量具有類的特征,引入包裝類。
2.基本資料類型與對應的包裝類:
3.需要掌握的類型間的轉換:(基本資料類型、包裝類、String)
簡易版:
基本資料類型<—>包裝類:JDK 5.0 新特性:自動裝箱 與自動拆箱
基本資料類型、包裝類—>String:調用String重載的valueOf(Xxx xxx)
String—>基本資料類型、包裝類:調用包裝類的parseXxx(String s)
注意:轉換時,可能會報NumberFormatException
String類
1.概述
String:字元串,使用一對""引起來表示。
- String聲明為final的,不可被繼承
-
String實作了Serializable接口:表示字元串是支援序列化的。
實作了Comparable接口:表示String可以比較大小
- String内部定義了final char[] value用于存儲字元串資料
- 通過字面量的方式(差別于new給一個字元串指派,此時的字元串值聲明在字元串常量池中)。
- 字元串常量池中是不會存儲相同内容(使用String類的equals()比較,傳回true)的字元串的。
2.String的不可變性
- 1.當對字元串重新指派時,需要重寫指定記憶體區域指派,不能使用原有的value進行指派。
- 2.當對現的字元串進行連接配接操作時,也需要重新指定記憶體區域指派,不能使用原有的value進行指派。
- 3.當調用String的replace()方法修改指定字元或字元串時,也需要重新指定記憶體區域指派,不能使用原有的value進行指派。
3.常用方法:
int length():傳回字元串的長度: return value.length
char charAt(int index): 傳回某索引處的字元return value[index]
boolean isEmpty():判斷是否是空字元串:return value.length == 0
String toLowerCase():使用預設語言環境,将 String 中的所字元轉換為小寫
String toUpperCase():使用預設語言環境,将 String 中的所字元轉換為大寫
String trim():傳回字元串的副本,忽略前導空白和尾部空白
boolean equals(Object obj):比較字元串的内容是否相同
boolean equalsIgnoreCase(String anotherString):與equals方法類似,忽略大小寫
String concat(String str):将指定字元串連接配接到此字元串的結尾。 等價于用“+”
int compareTo(String anotherString):比較兩個字元串的大小
String substring(int beginIndex):傳回一個新的字元串,它是此字元串的從beginIndex開始截取到最後的一個子字元串。
String substring(int beginIndex, int endIndex) :傳回一個新字元串,它是此字元串從beginIndex開始截取到endIndex(不包含)的一個子字元串。
boolean endsWith(String suffix):測試此字元串是否以指定的字尾結束
boolean startsWith(String prefix):測試此字元串是否以指定的字首開始
boolean startsWith(String prefix, int toffset):測試此字元串從指定索引開始的子字元串是否以指定字首開始
boolean contains(CharSequence s):當且僅當此字元串包含指定的 char 值序列時,傳回 true
int indexOf(String str):傳回指定子字元串在此字元串中第一次出現處的索引
int indexOf(String str, int fromIndex):傳回指定子字元串在此字元串中第一次出現處的索引,從指定的索引開始
int lastIndexOf(String str):傳回指定子字元串在此字元串中最右邊出現處的索引
int lastIndexOf(String str, int fromIndex):傳回指定子字元串在此字元串中最後一次出現處的索引,從指定的索引開始反向搜尋
注:indexOf和lastIndexOf方法如果未找到都是傳回-1
替換:
String replace(char oldChar, char newChar):傳回一個新的字元串,它是通過用 newChar 替換此字元串中出現的所 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替換序列替換此字元串所比對字面值目标序列的子字元串。
String replaceAll(String regex, String replacement):使用給定的 replacement 替換此字元串所比對給定的正規表達式的子字元串。
String replaceFirst(String regex, String replacement):使用給定的 replacement 替換此字元串比對給定的正規表達式的第一個子字元串。
比對:
boolean matches(String regex):告知此字元串是否比對給定的正規表達式。
切片:
String[] split(String regex):根據給定正規表達式的比對拆分此字元串。
String[] split(String regex, int limit):根據比對給定的正規表達式來拆分此字元串,最多不超過limit個,如果超過了,剩下的全部都放到最後一個元素中。
StringBuffer,StringBuilder類
1.String、StringBuffer、StringBuilder三者的對比
String:不可變的字元序列;底層使用char[]存儲
StringBuffer:可變的字元序列;線程安全的,效率低;底層使用char[]存儲
StringBuilder:可變的字元序列;jdk5.0新增的,線程不安全的,效率高;底層使用char[]存儲
2.StringBuffer、StringBuilder中的常用方法
增:append(xxx)
删:delete(int start,int end)
改:setCharAt(int n ,char ch) / replace(int start, int end, String str)
查:charAt(int n )
插:insert(int offset, xxx)
長度:length();
*周遊:for() + charAt() / toString()
關于日期時間的API
比較器
Java中的對象,正常情況下,隻能進行比較:== 或 != 。不能使用 > 或 < 的
但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小。
如何實作?使用兩個接口中的任何一個:Comparable 或 Comparator
自然排序:使用Comparable接口
- 1.像String、包裝類等實作了Comparable接口,重寫了compareTo(obj)方法,給出了比較兩個對象大小的方式。
- 2.像String、包裝類重寫compareTo()方法以後,進行了從小到大的排列
-
3.重寫compareTo(obj)的規則:
如果目前對象this大于形參對象obj,則傳回正整數;
如果目前對象this小于形參對象obj,則傳回負整數, 如果目前對象this等于形參對象obj,則傳回零。
- 對于自定義類來說,如果需要排序,我們可以讓自定義類實作Comparable接口,重寫compareTo(obj)方法。在compareTo(obj)方法中指明如何排序
定制排序:使用Comparator接口
3.1 說明
1.背景:
當元素的類型沒實作java.lang.Comparable接口而又不友善修改代碼,或者實作了java.lang.Comparable接口的排序規則不适合目前的操作,那麼可以考慮使用 Comparator 的對象來排序
2.重寫compare(Object o1,Object o2)方法,比較o1和o2的大小:
如果方法傳回正整數,則表示o1大于o2;
如果傳回0,表示相等;
傳回負整數,表示o1小于o2。
枚舉類
枚舉類的說明:
- 1.枚舉類的了解:類的對象隻有有限個,确定的。我們稱此類為枚舉類
- 2.當需要定義一組常量時,強烈建議使用枚舉類
- 3.如果枚舉類中隻一個對象,則可以作為單例模式的實作方式。
注解
注解的了解
① jdk 5.0 新增的功能
② Annotation 其實就是代碼裡的特殊标記, 這些标記可以在編譯, 類加載, 運作時被讀取, 并執行相應的處理。通過使用 Annotation,
程式員可以在不改變原邏輯的情況下, 在源檔案中嵌入一些補充資訊。
③在JavaSE中,注解的使用目的比較簡單,例如标記過時的功能,忽略警告等。在JavaEE/Android
中注解占據了更重要的角色,例如用來配置應用程式的任何切面,代替JavaEE舊版中所遺留的繁冗代碼和XML配置等。
集合
詳情可見集合總結。
IO流
流的分類
- 1.操作資料機關:位元組流、字元流
- 2.資料的流向:輸入流、輸出流
- 3.流的角色:節點流、處理流
輸入過程
① 建立File類的對象,指明讀取的資料的來源。(要求此檔案一定要存在)
② 建立相應的輸入流,将File類的對象作為參數,傳入流的構造器中
③ 具體的讀入過程:
建立相應的byte[] 或 char[]。
④ 關閉流資源
說明:程式中出現的異常需要使用try-catch-finally處理。
輸出過程
① 建立File類的對象,指明寫出的資料的位置。(不要求此檔案一定要存在)
② 建立相應的輸出流,将File類的對象作為參數,傳入流的構造器中
③ 具體的寫出過程:
write(char[]/byte[] buffer,0,len)
④ 關閉流資源
說明:程式中出現的異常需要使用try-catch-finally處理。
泛型
1.泛型的概念
所謂泛型,就是允許在定義類、接口時通過一個辨別表示類中某個屬性的類型或者是某個方法的返
回值及參數類型。這個類型參數将在使用時(例如,繼承或實作這個接口,用這個類型聲明變量、
建立對象時确定(即傳入實際的類型參數,也稱為類型實參)。
2.泛型的引入背景
集合容器類在設計階段/聲明階段不能确定這個容器到底實際存的是什麼類型的對象,是以在JDK1.5之前隻能把元素類型設計為Object,JDK1.5之後使用泛型來解決。因為這個時候除了元素的類型不确定,其他的部分是确定的,例如關于這個元素如何儲存,如何管理等是确定的,是以此時把元素的類型設計成一個參數,這個類型參數叫做泛型。Collection,List,ArrayList 這個就是類型參數,即泛型。
3.在集合中使用泛型的情況
網絡程式設計
一、實作網絡通信需要解決的兩個問題
- 1.如何準确地定位網絡上一台或多台主機;定位主機上的特定的應用
- 2.找到主機後如何可靠高效地進行資料傳輸
二、網絡通信的兩個要素:
- 1.對應問題一:IP和端口号
- 2.對應問題二:提供網絡通信協定:TCP/IP參考模型(應用層、傳輸層、網絡層、實體+資料鍊路層)
三、通信要素一:IP和端口号
1.IP的了解
- 1.IP:唯一的辨別 Internet 上的計算機(通信實體)
- 2.在Java中使用InetAddress類代表IP
- 3.IP分類:IPv4 和 IPv6 ; 網際網路 和 區域網路
- 4.域名: www.baidu.com www.mi.com www.sina.com www.jd.com
- 域名解析:域名容易記憶,當在連接配接網絡時輸入一個主機的域名後,域名伺服器(DNS)負責将域名轉化成IP位址,這樣才能和主機建立連接配接。 -------域名解析
- 5.本地回路位址:127.0.0.1 對應着:localhost
2.InetAddress類:此類的一個對象就代表着一個具體的IP位址
- 2.1執行個體化 getByName(String host) 、 getLocalHost()
- 2.2常用方法 getHostName() / getHostAddress()
3.端口号:正在計算機上運作的程序。
- 要求:不同的程序不同的端口号
- 範圍:被規定為一個 16 位的整數 0~65535。
端口号與IP位址的組合得出一個網絡套接字:Socket
4.TCP和UDP的差別
5.TCP三向交握和四次揮手
反射
擷取Class類的執行個體
擷取Class執行個體的幾種方式:
//方式一:調用運作時類的屬性:.class
Class clazz1 = Person.class;
System.out.println(clazz1);
//方式二:通過運作時類的對象,調用getClass()
Person p1 = new Person();
Class clazz2 = p1.getClass();
System.out.println(clazz2);
//方式三:調用Class的靜态方法:forName(String classPath)
Class clazz3 = Class.forName("com.atguigu.java.Person");
// clazz3 = Class.forName("java.lang.String");
System.out.println(clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz1 == clazz3);
反射的四大應用
應用一:建立運作時類的對象
代碼舉例
Class<Person> clazz = Person.class;
Person obj = clazz.newInstance();
System.out.println(obj);
說明
newInstance():調用此方法,建立對應的運作時類的對象。内部調用了運作時類的空參的構造器。
要想此方法正常的建立運作時類的對象,要求:
1.運作時類必須提供空參的構造器
2.空參的構造器的通路權限得夠。通常,設定為public
應用二:擷取運作時類的完整結構
我們可以通過反射,擷取對應的運作時類中所有的屬性、方法、構造器、父類、接口、父類的泛型、包、注解、異常等。
典型代碼:
@Test
public void test1(){
Class clazz = Person.class;
//擷取屬性結構
//getFields():擷取目前運作時類及其父類中聲明為public通路權限的屬性
Field[] fields = clazz.getFields();
for(Field f : fields){
System.out.println(f);
}
System.out.println();
//getDeclaredFields():擷取目前運作時類中聲明的所屬性。(不包含父類中聲明的屬性
Field[] declaredFields = clazz.getDeclaredFields();
for(Field f : declaredFields){
System.out.println(f);
}
}
@Test
public void test1(){
Class clazz = Person.class;
//getMethods():擷取目前運作時類及其所父類中聲明為public權限的方法
Method[] methods = clazz.getMethods();
for(Method m : methods){
System.out.println(m);
}
System.out.println();
//getDeclaredMethods():擷取目前運作時類中聲明的所方法。(不包含父類中聲明的方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for(Method m : declaredMethods){
System.out.println(m);
}
}
/*
擷取構造器結構
*/
@Test
public void test1(){
Class clazz = Person.class;
//getConstructors():擷取目前運作時類中聲明為public的構造器
Constructor[] constructors = clazz.getConstructors();
for(Constructor c : constructors){
System.out.println(c);
}
System.out.println();
//getDeclaredConstructors():擷取目前運作時類中聲明的所的構造器
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
for(Constructor c : declaredConstructors){
System.out.println(c);
}
}
/*
擷取運作時類的父類
*/
@Test
public void test2(){
Class clazz = Person.class;
Class superclass = clazz.getSuperclass();
System.out.println(superclass);
}
/*
擷取運作時類的帶泛型的父類
*/
@Test
public void test3(){
Class clazz = Person.class;
Type genericSuperclass = clazz.getGenericSuperclass();
System.out.println(genericSuperclass);
}
/*
擷取運作時類的帶泛型的父類的泛型
代碼:邏輯性代碼 vs 功能性代碼
*/
@Test
public void test4(){
Class clazz = Person.class;
Type genericSuperclass = clazz.getGenericSuperclass();
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
//擷取泛型類型
Type[] actualTypeArguments = paramType.getActualTypeArguments();
// System.out.println(actualTypeArguments[0].getTypeName());
System.out.println(((Class)actualTypeArguments[0]).getName());
}
/*
擷取運作時類實作的接口
*/
@Test
public void test5(){
Class clazz = Person.class;
Class[] interfaces = clazz.getInterfaces();
for(Class c : interfaces){
System.out.println(c);
}
System.out.println();
//擷取運作時類的父類實作的接口
Class[] interfaces1 = clazz.getSuperclass().getInterfaces();
for(Class c : interfaces1){
System.out.println(c);
}
}
/*
擷取運作時類所在的包
*/
@Test
public void test6(){
Class clazz = Person.class;
Package pack = clazz.getPackage();
System.out.println(pack);
}
/*
擷取運作時類聲明的注解
*/
@Test
public void test7(){
Class clazz = Person.class;
Annotation[] annotations = clazz.getAnnotations();
for(Annotation annos : annotations){
System.out.println(annos);
}
}
應用三:調用運作時類的完整結構
調用指定的屬性:
@Test
public void testField1() throws Exception {
Class clazz = Person.class;
//建立運作時類的對象
Person p = (Person) clazz.newInstance();
//1. getDeclaredField(String fieldName):擷取運作時類中指定變量名的屬性
Field name = clazz.getDeclaredField("name");
//2.保證目前屬性是可通路的
name.setAccessible(true);
//3.擷取、設定指定對象的此屬性值
name.set(p,"Tom");
System.out.println(name.get(p));
}
調用指定的方法:
@Test
public void testMethod() throws Exception {
Class clazz = Person.class;
//建立運作時類的對象
Person p = (Person) clazz.newInstance();
/*
1.擷取指定的某個方法
getDeclaredMethod():參數1 :指明擷取的方法的名稱 參數2:指明擷取的方法的形參清單
*/
Method show = clazz.getDeclaredMethod("show", String.class);
//2.保證目前方法是可通路的
show.setAccessible(true);
/*
3. 調用方法的invoke():參數1:方法的調用者 參數2:給方法形參指派的實參
invoke()的傳回值即為對應類中調用的方法的傳回值。
*/
Object returnValue = show.invoke(p,"CHN"); //String nation = p.show("CHN");
System.out.println(returnValue);
System.out.println("*************如何調用靜态方法*****************");
// private static void showDesc()
Method showDesc = clazz.getDeclaredMethod("showDesc");
showDesc.setAccessible(true);
//如果調用的運作時類中的方法沒傳回值,則此invoke()傳回null
// Object returnVal = showDesc.invoke(null); 因為靜态方法是跟着類的,類其實在獲得方法時已經指明了,是以調用者其實已經确定了,是以不用指明調用者自然也是可以的
Object returnVal = showDesc.invoke(Person.class);
System.out.println(returnVal);//null
}
調用指定的構造器:
@Test
public void testConstructor() throws Exception {
Class clazz = Person.class;
//private Person(String name)
/*
1.擷取指定的構造器
getDeclaredConstructor():參數:指明構造器的參數清單
*/
Constructor constructor = clazz.getDeclaredConstructor(String.class);
//2.保證此構造器是可通路的
constructor.setAccessible(true);
//3.調用此構造器建立運作時類的對象
Person per = (Person) constructor.newInstance("Tom");
System.out.println(per);
}
應用四:動态代理
代理模式的原理:
使用一個代理将對象包裝起來, 然後用該代理對象取代原始對象。任何對原始對象的調用都要通過代理。代理對象決定是否以及何時将方法調用轉到原始對象上。
動态代理的實作
需要解決的兩個主要問題:
問題一:如何根據加載到記憶體中的被代理類,動态的建立一個代理類及其對象。
(通過Proxy.newProxyInstance()實作)
問題二:當通過代理類的對象調用方法a時,如何動态的去調用被代理類中的同名方法a。
(通過InvocationHandler接口的實作類及其方法invoke())
代碼實作:
interface Human{
String getBelief();
void eat(String food);
}
//被代理類
class SuperMan implements Human{
@Override
public String getBelief() {
return "I believe I can fly!";
}
@Override
public void eat(String food) {
System.out.println("我喜歡吃" + food);
}
}
class HumanUtil{
public void method1(){
System.out.println("====================通用方法一====================");
}
public void method2(){
System.out.println("====================通用方法二====================");
}
}
class ProxyFactory{
//調用此方法,傳回一個代理類的對象。解決問題一
public static Object getProxyInstance(Object obj){//obj:被代理類的對象
MyInvocationHandler handler = new MyInvocationHandler();
handler.bind(obj);
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
}
}
class MyInvocationHandler implements InvocationHandler{
private Object obj;//需要使用被代理類的對象進行指派
public void bind(Object obj){
this.obj = obj;
}
//當我們通過代理類的對象,調用方法a時,就會自動的調用如下的方法:invoke()
//将被代理類要執行的方法a的功能就聲明在invoke()中
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HumanUtil util = new HumanUtil();
util.method1();
//method:即為代理類對象調用的方法,此方法也就作為了被代理類對象要調用的方法
//obj:被代理類的對象
Object returnValue = method.invoke(obj,args);
util.method2();
//上述方法的傳回值就作為目前類中的invoke()的傳回值。
return returnValue;
}
}
public class ProxyTest {
public static void main(String[] args) {
SuperMan superMan = new SuperMan();
//proxyInstance:代理類的對象
Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
//當通過代理類對象調用方法時,會自動的調用被代理類中同名的方法
String belief = proxyInstance.getBelief();
System.out.println(belief);
proxyInstance.eat("四川麻辣燙");
System.out.println("*****************************");
NikeClothFactory nikeClothFactory = new NikeClothFactory();
ClothFactory proxyClothFactory = (ClothFactory) ProxyFactory.getProxyInstance(nikeClothFactory);
proxyClothFactory.produceCloth();
}
}
思路:
我們設定ProxyFactory為生産動态代理類的工廠,其設定一個傳入的參數為要代理的對象,工廠内部設定一個靜态方法,根據代理的對象及其一些屬性來生成代理類的對象,這裡直接使用newProxyInstance方法封裝了。即這個方法内部自己給我們造出對象了,隻要我們給他足夠的細節即可。
但是有一個接口的實作類需要我們提供,這個玩意是為了實作我們“調用代理類的對象的方法,其實本質是調用被代理類的對象方法”。
通過它,我們可以實作當我們通過代理類的對象,調用方法a時,就會自動的調用如下的方法:invoke()
在這個invoke方法内部,來完成我們想調用代理類對象方法的具體實作,由于給了許多參數,直接根據參數通過反射思想調用反射中的invoke方法即可。
這種動态代理是怎麼建成的呢?
主要是中間部分是抽象的,可以根據你輸入的被代理類的類型來确定執行什麼東西,是以相當于無形中建立了好多的代理類。
java8新特性
Stream流
詳情可見Stream總結。