1 網路編程
1 什么是計算機之間的通信協議
是計算機與計算機之間交流的標準 .
是對資料的 傳輸速率, 傳入介面, 步驟控制 出錯控制 等等 制定的一套標準 !
常用的通信協議:
- http協議 : 超文本傳輸協議 . 80埠號
- https協議: 安全的超文本傳輸協議 443埠號
- ftp協議: 檔案傳輸協議 21埠號
- TCP協議: 傳輸控制協議
- UDP協議: 資料報協議
2 網路編程的分類
1.B/S 程式 : 瀏覽器與服務器程式
2 C/S 程式 : 客戶端與服務器程式
3 TCP協議 - OSI網路模型
指的是 從一臺計算機的軟體中, 將資料發送到另一臺計算機的軟體中的程序.
七層網路模型: 應用層 / 表現層 / 會話層 / 傳輸層 / 網路層 / 資料鏈路層 / 物理層
需要使用到兩個類, 來撰寫TCP協議的 CS程式 .
1.ServerSocket 搭建服務器
2.Socket 搭建客戶端
兩方使用socket(套接字 , 通信端點) 進行交流
ServerSocket
用于創建服務器 . 創建完畢后, 會系結一個埠號.
然后此服務器可以等待客戶端連接 .
每連接一個客戶端 , 服務器就會得到一個新的Socket物件, 用于跟客戶端進行通信 .
常用構造方法
ServerSocket(int port); ****
創建一個基于TCP/IP協議的服務器 , 并系結指定的埠號.
注意: 引數port的范圍是: 0-65535 (建議1025-65535)
常用方法
Socket accept(); ****
等待客戶端連接 .
此方法會導致執行緒的阻塞!
直到一個新的客戶端連接成功, return Socket物件后, 執行緒在繼續執行.
void close();
釋放占用的埠號 , 關閉服務器.
Socket
是兩臺計算機之間通信的端點 , 是網路驅動提供給應用程式編程的一種介面 一套標準, 一種機制 .
構造方法:
Socket(String ip,int port) ****
創建一個套接字, 并連接指定ip和埠號的 服務器.
引數1. 服務器的ip地址
引數2. 服務器軟體的埠號…
常用方法:
- OutputStream getOutputStream();
回傳的是 , 指向通信的另一端點的輸出流 - InputStream getInputStream();
回傳的是 , 指向通信的另一端點的輸入流 - void close();
關閉套接字
注意:
在網路編程時, 獲取輸入輸出流的操作 ,對于客戶端與服務器來說是相對的
客戶端的輸入流, 輸入的是服務器的輸出流 輸出的內容.
客戶端的暑促劉, 輸出到了服務器的輸入流中.
所以 在使用時, 需要注意以下一點規則:
客戶端與服務器獲取流的順序必須是相反的:
例如:
客戶端先得到了輸入流 , 那服務器必須先獲取輸出流
案例:
客戶端:
//1. 連接服務器
Socket socket = new Socket("192.168.102.228",8888);
//2. 得到輸出流
//2.1 得到輸出流
OutputStream os = socket.getOutputStream();
//2.2 將輸出流, 轉換為列印流
PrintStream ps = new PrintStream(os);
//3. 得到輸入流
//3.1 得到輸入流
InputStream is = socket.getInputStream();
//3.2 將位元組輸入流, 轉換為字符輸入流 , 并轉換為逐行讀取流InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
//4. 回圈接收用戶輸入
Scanner input = new Scanner(System.in);
while(true) {
System.out.println("請輸入要發送給服務器的內容:");
String text1 = input.nextLine();
//5. 將用戶輸入的內容, 發送給服務器
ps.println(text1);
//6. 接收服務器回復的訊息
String text2 = br.readLine();
System.out.println(text2);
if("886".equals(text1)) {
break;
}
}
服務器:
public static void main(String[] args) throws Exception {
//1. 啟動服務器, 并偵聽8888埠號
ServerSocket server = new ServerSocket(8888);
//2. 列印提示
System.out.println("服務器已啟動 , 等待客戶端連接中...");
//3. 等待客戶端連接
Socket socket = server.accept();
System.out.println("一個客戶端連接成功:"+socket.getInetAddress().toString());
//4. 獲取輸入流
//4.1 獲取輸入流
InputStream is = socket.getInputStream();
//4.2 將輸入的位元組流 ,轉換為字符流
InputStreamReader isr = new InputStreamReader(is);
//4.3 將字符流, 轉換為逐行讀取流
BufferedReader br = new BufferedReader(isr);
//5. 獲取輸出流
//5.1 獲取輸出流
OutputStream os = socket.getOutputStream();
//5.2 將位元組輸出流, 轉換為列印流
PrintStream ps = new PrintStream(os);
while(true) {
//6. 回圈讀取一行行的資料 ,讀取操作會導致執行緒的阻塞, 直到客戶端真的發送了資料,
//服務器才能接到, 順序繼續執行下面的代碼
String text = br.readLine();
//7. 將這個文字, 再列印給客戶端
ps.println("服務器:"+text);
if("886".equals(text)) {
break;
}
}

互相傳遞訊息:
先啟動服務器:

啟動客戶端:

在服務器中加入多執行緒方法(但是一定要保證順序一方輸入另一方輸出):

2網路的七層架構
1 七層架構
7 層模型主要包括:
- 物理層:主要定義物理設備標準,如網線的介面型別、光纖的介面型別、各種傳輸介質的傳輸速率等,它的主要作用是傳輸位元流(就是由 1、0 轉化為電流強弱來進行傳輸,到達目的地后在轉化為1、0,也就是我們常說的模數轉換與數模轉換),這一層的資料叫做位元,
- 資料鏈路層:主要將從物理層接收的資料進行 MAC 地址(網卡的地址)的封裝與解封裝,常把這一層的資料叫做幀,在這一層作業的設備是交換機,資料通過交換機來傳輸,
- 網路層:主要將從下層接收到的資料進行 IP 地址(例 192.168.0.1)的封裝與解封裝,在這一層作業的設備是路由器,常把這一層的資料叫做資料包,
- 傳輸層:定義了一些傳輸資料的協議和埠號(WWW 埠 80 等),如:TCP(傳輸控制協議,傳輸效率低,可靠性強,用于傳輸可靠性要求高,資料量大的資料),UDP(用戶資料報協議,與 TCP 特性恰恰相反,用于傳輸可靠性要求不高,資料量小的資料,如 QQ 聊天資料就是通過這種方式傳輸的), 主要是將從下層接收的資料進行分段進行傳輸,到達目的地址后在進行重組,
常常把這一層資料叫欄位, - 會話層:通過傳輸層(埠號:傳輸埠與接收埠)建立資料傳輸的通路,主要在你的系統之間發起會話或或者接受會話請求(設備之間需要互相認識可以是 IP 也可以是 MAC 或者是主機名)
- 表示層:主要是進行對接收的資料進行解釋、加密與解密、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉換成人能夠能識別的東西(如圖片、聲音等))
- 應用層 主要是一些終端的應用,比如說FTP(各種檔案下載),WEB(IE瀏覽),QQ之類的(你就把它理解成我們在電腦螢屏上可以看到的東西.就 是終端應用),

2
2 TCP/IP 原理
TCP/IP 協議不是 TCP 和 IP 這兩個協議的合稱,而是指因特網整個 TCP/IP 協議族,從協議分層模型方面來講,TCP/IP 由四個層次組成:網路介面層、網路層、傳輸層、應用層,

3 TCP 三次握手/四次揮手
TCP 在傳輸之前會進行三次溝通,一般稱為“三次握手”,傳完資料斷開的時候要進行四次溝通,一般稱為“四次揮手”,
4 HTTP 原理
HTTP 是一個無狀態的協議,無狀態是指客戶機(Web 瀏覽器)和服務器之間不需要建立持久的連接,這意味著當一個客戶端向服務器端發出請求,然后服務器回傳回應(response),連接就被關閉了,在服務器端不保留連接的有關資訊.HTTP 遵循請求(Request)/應答(Response)模型,客戶機(瀏覽器)向服務器發送請求,服務器處理請求并回傳適當的應答,所有 HTTP 連接都被構造成一套請求和應答,
4.1 傳輸流程
1:地址決議
如用客戶端瀏覽器請求這個頁面:http://localhost.com:8080/index.html 從中分解出協議名、主機名、埠、物件路徑等部分,對于我們的這個地址,決議得到的結果如下:
協議名:http
主機名:localhost.com
埠:8080
物件路徑:/index.html
在這一步,需要域名系統 DNS 決議域名 localhost.com,得主機的 IP 地址,
2:封裝 HTTP 請求資料包
把以上部分結合本機自己的資訊,封裝成一個 HTTP 請求資料包
3:封裝成 TCP 包并建立連接
封裝成 TCP 包,建立 TCP 連接(TCP 的三次握手)
4:客戶機發送請求命
4)客戶機發送請求命令:建立連接后,客戶機發送一個請求給服務器,請求方式的格式為:統一資
源識別符號(URL)、協議版本號,后邊是 MIME 資訊包括請求修飾符、客戶機資訊和可內容,
5:服務器回應
服務器接到請求后,給予相應的回應資訊,其格式為一個狀態行,包括資訊的協議版本號、一個成功或錯誤的代碼,后邊是 MIME 資訊包括服務器資訊、物體資訊和可能的內容,
6:服務器關閉 TCP 連接
服務器關閉 TCP 連接:一般情況下,一旦 Web 服務器向瀏覽器發送了請求資料,它就要關閉 TCP 連接,然后如果瀏覽器或者服務器在其頭資訊加入了這行代碼 Connection:keep-alive,TCP 連接在發送后將仍然保持打開狀態,于是,瀏覽器可以繼續通過相同的連接發送請求,保持連接節省了為每個請求建立新連接所需的時間,還節約了網路帶寬,

7 Http 狀態


5 HTTPS
HTTPS(全稱:Hypertext Transfer Protocol over Secure Socket Layer),是以安全為目標的HTTP 通道,簡單講是 HTTP 的安全版,即 HTTP 下加入 SSL 層,HTTPS 的安全基礎是 SSL,其所用的埠號是 443, 程序大致如下
建立連接獲取證書
1) SSL 客戶端通過 TCP 和服務器建立連接之后(443 埠),并且在一般的 tcp 連接協商(握手)程序中請求證書,即客戶端發出一個訊息給服務器,這個訊息里面包含了自己可實作的演算法串列和其它一些需要的訊息,SSL 的服務器端會回應一個資料包,這里面確定了這次通信所需要的演算法,然后服務器向客戶端回傳證書,(證書里面包含了服務器資訊:域名,申請證書的公司,公共秘鑰),
證書驗證
2) Client 在收到服務器回傳的證書后,判斷簽發這個證書的公共簽發機構,并使用這個機構的公共秘鑰確認簽名是否有效,客戶端還會確保證書中列出的域名就是它正在連接的域名,資料加密和傳輸
3) 如果確認證書有效,那么生成對稱秘鑰并使用服務器的公共秘鑰進行加密,然后發送給服務器,服務器使用它的私鑰對它進行解密,這樣兩臺計算機可以開始進行對稱加密進行通信,

3 XML
Java中有幾種XML決議方式 ? 分別是什么 ? 有什么樣的優缺點 ?
答: 四種.
1. SAX決議
決議方式是事件驅動機制 !
SAX決議器, 逐行讀取XML檔案決議 , 每當決議到一個標簽的開始/結束/內容/屬性時,觸發事件.我們可以撰寫程式在這些事件發生時, 進行相應的處理.
優點:
分析能夠立即開始,而不是等待所有的資料被處理逐行加載,節省記憶體.有助于決議大于系統記憶體的檔案有時不必決議整個檔案,它可以在某個條件得到滿足時停止決議.
缺點:
1.單向決議,無法定位檔案層次,無法同時訪問同一檔案的不同部分資料(因為逐
行決議, 當決議第n行是, 第n-1行已經被釋放了, 無法在進行操作了).
2. 無法得知事件發生時元素的層次, 只能自己維護節點的父/子關系.
3. 只讀決議方式, 無法修改XML檔案的內容.
2. DOM決議
是用與平臺和語言無關的方式表示XML檔案的官方W3C標準,分析該結構通常需要加載整個檔案和記憶體中建立檔案樹模型.程式員可以通過操作檔案樹, 來完成資料的獲取 修改 洗掉等.
優點:
檔案在記憶體中加載, 允許對資料和結構做出更改.
訪問是雙向的,可以在任何時候在樹中雙向決議資料,
缺點:
檔案全部加載在記憶體中 , 消耗資源大.
3. JDOM決議
目的是成為Java特定檔案模型,它簡化與XML的互動并且比使用DOM實作更快,由于是第一個Java特定模型,JDOM一直得到大力推廣和促進,
JDOM檔案宣告其目的是“使用20%(或更少)的精力解決80%(或更多)Java/XML問題”(根據學習曲線假定為20%)
優點:
使用具體類而不是介面,簡化了DOM的API,
大量使用了Java集合類,方便了Java開發人員,
缺點:
沒有較好的靈活性,
性能不是那么優異,
4. DOM4J決議
它是JDOM的一種智能分支,它合并了許多超出基本XML檔案表示的功能,包括集成的XPath支持、XML Schema支持以及用于大檔案或流化檔案的基于事件的處理,它還提供了構建檔案表示的選項,DOM4J是一個非常優秀的Java XML API,具有性能優異、功能強大和極端易用使用的特點,同時它也是一個開放源代碼的軟體,如今你可以看到越來越多的Java軟體都在使用DOM4J來讀寫XML,
目前許多開源專案中大量采用DOM4J , 例如:Hibernate,
DOM4J決議XML 掌握
步驟:
- 引入jar檔案 dom4j.jar
- 創建一個指向XML檔案的輸入流
FileInputStream fis = new FileInputStream(“xml檔案的地址”); - 創建一個XML讀取工具物件
SAXReader sr = new SAXReader(); - 使用讀取工具物件, 讀取XML檔案的輸入流 , 并得到檔案物件
Document doc = sr.read(fis); - 通過檔案物件, 獲取XML檔案中的根元素物件
Element root = doc.getRootElement();
xml檔案有兩種定義方法:
dtd:資料型別定義(data type definition),用以描述XML檔案的檔案結構,是早期的XML檔案定義形式,
schema:其本身是基于XML語言撰寫的,在型別和語法上的限定能力比dtd強,處理也比較方便,因為此正逐漸代替dtd成為新的模式定義語言,
4 JSON
JSON: JavaScript Object Notation JS物件簡譜 , 是一種輕量級的資料交換格式.
Java和JSON可以互相轉換,
Json分為兩種 :
Gson
將物件轉換成JSON字串
轉換JSON字串的步驟:
- 引入JAR包
- 在需要轉換JSON字串的位置撰寫如下代碼即可:
String json = new Gson().toJSON(要轉換的物件);
案例:
Book b = BookDao.find();
String json = new Gson().toJson(b);
System.out.println(json);
將JSON字串轉換成物件:
- 引入JAR包
- 在需要轉換Java物件的位置, 撰寫如下代碼:
物件 = new Gson().fromJson(JSON字串,物件型別.class);
案例:

FastJson
j

5 注解
簡介
Java 注解(Annotation)又稱 Java 標注,是 JDK5.0 引入的一種注釋機制,
Java 語言中的類、方法、變數、引數和包等都可以被標注,和注釋不同,Java 標注可以通過反射獲取標注內容,在編譯器生成類檔案時,標注可以被嵌入到位元組碼中,Java 虛擬機可以保留標注內容,在運行時可以獲取到標注內容 , 當然它也支持自定義 Java 標注,
主要用于:
編譯格式檢查 反射中決議 生成幫助檔案 跟蹤代碼依賴等
學習的重點
理解 Annotation 的關鍵,是理解 Annotation 的語法和用法.
內置注解
@Override : 重寫 *
定義在java.lang.Override
@Deprecated:廢棄 *
private Level(int levelValue) {
this.levelValue = levelValue;
}
public int getLevelValue() {
return levelValue;
}
}
- 概念定義在java.lang.Deprecated
@SafeVarargs
Java 7 開始支持,忽略任何使用引數為泛型變數的方法或建構式呼叫產生的警告,
@FunctionalInterface: 函式式介面 *
Java 8 開始支持,標識一個匿名函式或函式式介面,
@Repeatable:標識某注解可以在同一個宣告上使用多次
Java 8 開始支持,標識某注解可以在同一個宣告上使用多次,

關鍵字 用途
all 抑制所有警告
boxing 抑制裝箱、拆箱操作時候的警告
cast 抑制映射相關的警告
dep-ann 抑制啟用注釋的警告
deprecation 抑制過期方法警告
fallthrough 抑制確在switch中缺失breaks的警告
finally 抑制finally模塊沒有回傳的警告
hiding 抑制相對于隱藏變數的區域變數的警告
incomplete-switch 忽略沒有完整的switch陳述句
nls 忽略非nls格式的字符
null 忽略對null的操作
rawtypes 使用generics時忽略沒有指定相應的型別
restriction 抑制禁止使用勸阻或禁止參考的警告
serial 忽略在serializable類中沒有宣告serialVersionUID變數
static-access 抑制不正確的靜態訪問方式警告
synthetic-access 抑制子類沒有按最優方法訪問內部類的警告
unchecked 抑制沒有進行型別檢查操作的警告
unqualified-field-access 抑制沒有權限訪問的域的警告
unused 抑制沒被使用過的代碼的警告


看另一個案例:
未加注解前,他是暗的

加了忽略所有警告后 變亮了:

元注解
簡介 作用在其他注解的注解
元注解有哪些?
@Retention - 標識這個注解怎么保存,是只在代碼中,還是編入class檔案中,或者是在運行時可
以通過反射訪問,
@Documented - 標記這些注解是否包含在用戶檔案中 javadoc,
@Target - 標記這個注解應該是哪種 Java 成員,
@Inherited - 標記這個注解是自動繼承的

自定義注解:

01) Annotation與RetentionPolicy 與ElementType ,
每 1 個 Annotation 物件,都會有唯一的 RetentionPolicy 屬性;至于 ElementType 屬性,則有 1~n個,
(02) ElementType(注解的用途型別)
“每 1 個 Annotation” 都與 “1~n 個 ElementType” 關聯,當 Annotation 與某個 ElementType 關聯時,就意味著:Annotation有了某種用途,例如,若一個 Annotation 物件是 METHOD 型別,則該Annotation 只能用來修飾方法,
package java.lang.annotation;
public enum ElementType {
TYPE, /* 類、介面(包括注釋型別)或列舉宣告 */
FIELD, /* 欄位宣告(包括列舉常量) */
METHOD, /* 方法宣告 */
PARAMETER, /* 引數宣告 */
CONSTRUCTOR, /* 構造方法宣告 */
LOCAL_VARIABLE, /* 區域變數宣告 */
ANNOTATION_TYPE, /* 注釋型別宣告 */
PACKAGE /* 包宣告 */
}
(03) RetentionPolicy(注解作用域策略),
“每 1 個 Annotation” 都與 “1 個 RetentionPolicy” 關聯,
a) 若 Annotation 的型別為 SOURCE,則意味著:Annotation 僅存在于編譯器處理期間,編譯器處理完之后,該 Annotation 就沒用了, 例如," @Override" 標志就是一個 Annotation,當它修飾一個方法的時候,就意味著該方法覆寫父類的方法;并且在編譯期間會進行語法檢查!編譯器處理完后,"@Override" 就沒有任何作用了,
b) 若 Annotation 的型別為 CLASS,則意味著:編譯器將 Annotation 存盤于類對應的 .class 檔案中,它是 Annotation 的默認行為,
c) 若 Annotation 的型別為 RUNTIME,則意味著:編譯器將 Annotation 存盤于 class 檔案中,并且可由JVM讀入,
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE, /* Annotation資訊僅存在于編譯器處理期間,編譯器處理完之后就沒有該
Annotation資訊了 */
CLASS, /* 編譯器將Annotation存盤于類對應的.class檔案中,默認行為 */
RUNTIME /* 編譯器將Annotation存盤于class檔案中,并且可由JVM讀入 */
}
定義格式
@interface 自定義注解名{}
注意事項
- 定義的注解,自動繼承了java.lang,annotation.Annotation介面
- 注解中的每一個方法,實際是宣告的注解配置引數
- 方法的名稱就是 配置引數的名稱
方法的回傳值型別,就是配置引數的型別,只能是:基本型別/Class/String/enum - 可以通過default來宣告引數的默認值
- 如果只有一個引數成員,一般引數名為value
- 注解元素必須要有值,我們定義注解元素時,經常使用空字串、0作為默認值,
7 案例
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation1 {
引數型別 引數名() default 默認值;
}
上面的作用是定義一個 Annotation,我們可以在代碼中通過 “@MyAnnotation1” 來使用它,
@Documented, @Target, @Retention, @interface 都是來修飾 MyAnnotation1 的,含義:
(01) @interface
使用 @interface 定義注解時,意味著它實作了 java.lang.annotation.Annotation 介面,即該注解就是一個Annotation,
定義 Annotation 時,@interface 是必須的,
注意:它和我們通常的 implemented 實作介面的方法不同,Annotation 介面的實作細節都由編譯器完成,通過 @interface 定義注解后,該注解不能繼承其他的注解或介面,
(02) @Documented
類和方法的 Annotation 在預設情況下是不出現在 javadoc 中的,如果使用 @Documented 修飾該Annotation,則表示它可以出現在 javadoc 中,
定義 Annotation 時,@Documented 可有可無;若沒有定義,則 Annotation 不會出現在 javadoc中,
(03) @Target(ElementType.TYPE)
前面我們說過,ElementType 是 Annotation 的型別屬性,而 @Target 的作用,就是來指定Annotation 的型別屬性,
@Target(ElementType.TYPE) 的意思就是指定該 Annotation 的型別是 ElementType.TYPE,這就意味著,MyAnnotation1 是來修飾"類、介面(包括注釋型別)或列舉宣告"的注解,定義 Annotation 時,@Target 可有可無,若有 @Target,則該 Annotation 只能用于它所指定的地方;若沒有 @Target,則該 Annotation 可以用于任何地方,
(04) @Retention(RetentionPolicy.RUNTIME)
前面我們說過,RetentionPolicy 是 Annotation 的策略屬性,而 @Retention 的作用,就是指定Annotation 的策略屬性,
@Retention(RetentionPolicy.RUNTIME) 的意思就是指定該 Annotation 的策略是
RetentionPolicy.RUNTIME,這就意味著,編譯器會將該 Annotation 資訊保留在 .class 檔案中,并且能被虛擬機讀取,
定義 Annotation 時,@Retention 可有可無,若沒有 @Retention,則默認是
RetentionPolicy.CLASS,

可以傳參

可以給默認值:

6 反射
JAVA反射機制是在運行狀態中,獲取任意一個類的結構 , 創建物件 , 得到方法,執行方法 , 屬性 !;這種在運行狀態動態獲取資訊以及動態呼叫物件方法的功能被稱為java語言的反射機制,
6.1 反射的應用場合
編譯時型別和運行時型別
在 Java 程式中許多物件在運行時都會出現兩種型別:編譯時型別和運行時型別, 編譯時的型別由宣告物件時實用的型別來決定,運行時的型別由實際賦值給物件的型別決定 ,如:Person p=new Student();其中編譯時型別為 Person,運行時型別為 Student,的編譯時型別無法獲取具體方法
程式在運行時還可能接收到外部傳入的物件,該物件的編譯時型別為 Object,但是程式有需要呼叫該物件的運行時型別的方法,為了解決這些問題,程式需要在運行時發現物件和類的真實資訊,然而,如果編譯時根本無法預知該物件和類屬于哪些類,程式只能依靠運行時資訊來發現該物件和類的真實資訊,此時就必須使用到反射了,
6.2 Java 反射 API
反射 API 用來生成 JVM 中的類、介面或則物件的資訊,
- Class 類:反射的核心類,可以獲取類的屬性,方法等資訊,
- Field 類:Java.lang.reflec 包中的類,表示類的成員變數,可以用來獲取和設定類之中的屬性值,
- Method 類: Java.lang.reflec 包中的類,表示類的方法,它可以用來獲取類中的方法資訊或
者執行方法, - Constructor 類: Java.lang.reflec 包中的類,表示類的構造方法,
6.3 獲取 Class 物件的 3 種方法
1 呼叫某個物件的 getClass()方法
Person p=new Person();
Class clazz=p.getClass();
2 呼叫某個類的 class 屬性來獲取該類對應的 Class 物件
Class clazz=Person.class;
3 使用 Class 類中的 forName()靜態方法(最安全/性能最好)
Class clazz=Class.forName(“類的全路徑”); (最常用)
當我們獲得了想要操作的類的 Class 物件后,可以通過 Class 類中的方法獲取并查看該類中的方法和屬性,

//獲取 Person 類的 Class 物件
Class clazz=Class.forName("reflection.Person");13/04/2018 Page 105 of 283
//獲取 Person 類的所有方法資訊
Method[] method=clazz.getDeclaredMethods();
for(Method m:method){
System.out.println(m.toString());
}
//獲取 Person 類的所有成員屬性資訊
Field[] field=clazz.getDeclaredFields();
for(Field f:field){
System.out.println(f.toString());
}
//獲取 Person 類的所有構造方法資訊
Constructor[] constructor=clazz.getDeclaredConstructors();
for(Constructor c:constructor){
System.out.println(c.toString());
}
6.4 反射中的構造方法
1 通過指定的引數型別, 獲取指定的單個構造方法
getConstructor(引數型別的class物件陣列)
例如:
構造方法如下: Person(String name,int age)
得到這個構造方法的代碼如下:
Constructor c = p.getClass().getConstructor(String.class,int.class);
2. 獲取構造方法陣列
getConstructors();
3. 獲取所有權限的單個構造方法
getDeclaredConstructor(引數型別的class物件陣列)
4. 獲取所有權限的構造方法陣列
getDeclaredConstructors();

訪問私有構造方法時出錯,因為我們寫的那個私有方法是private,權限不允許

通過反射技術訪問私有構造方法:

6.5 獲取Method方法:
- getMethod(String methodName , class… clss)
根據引數串列的型別和方法名, 得到一個方法(public修飾的) - getMethods();
得到一個類的所有方法 (public修飾的) - getDeclaredMethod(String methodName , class… clss)
根據引數串列的型別和方法名, 得到一個方法(除繼承以外所有的:包含私有, 共有, 保護, 默認) - getDeclaredMethods();
得到一個類的所有方法 (除繼承以外所有的:包含私有, 共有, 保護, 默認)
Method執行方法
invoke(Object o,Object… para) :
呼叫方法 ,
引數1. 要呼叫方法的物件
引數2. 要傳遞的引數串列
getName()
獲取方法的方法名稱
setAccessible(boolean flag)
如果flag為true 則表示忽略訪問權限檢查 !(可以訪問任何權限的方法)

6.6 獲取Field
- getDeclaredField(String filedName)
根據屬性的名稱, 獲取一個屬性物件 (所有屬性) - getDeclaredFields()
獲取所有屬性 - getField(String filedName)
根據屬性的名稱, 獲取一個屬性物件 (public屬性) - getFields()
獲取所有屬性 (public)
Field屬性的物件型別
常用方法: - get(Object o );
引數: 要獲取屬性的物件
獲取指定物件的此屬性值 - set(Object o , Object value);
引數1. 要設定屬性值的 物件
引數2. 要設定的值
設定指定物件的屬性的值 - getName()
獲取屬性的名稱 - setAccessible(boolean flag)
如果flag為true 則表示忽略訪問權限檢查 !(可以訪問任何權限的屬性)

6.7 獲取注解資訊
獲取類/屬性/方法的全部注解物件
Annotation[] annotations01 = Class/Field/Method.getAnnotations();
for (Annotation annotation : annotations01) {
System.out.println(annotation);
}
根據型別獲取類/屬性/方法的注解物件
注解型別 物件名 = (注解型別) c.getAnnotation(注解型別.class);
這一篇文章對反射講的比較通透
對反射講的比較通俗易懂的個人感徑訓不錯
總的來說,學反射就一句話,動態編譯的時候想起它,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/291844.html
標籤:java
