主頁 > 後端開發 > java之-網路--注解---反射---xml

java之-網路--注解---反射---xml

2021-08-05 07:29:30 後端開發

1 網路編程

1 什么是計算機之間的通信協議

是計算機與計算機之間交流的標準 .
是對資料的 傳輸速率, 傳入介面, 步驟控制 出錯控制 等等 制定的一套標準 !
常用的通信協議:

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

步驟:

  1. 引入jar檔案 dom4j.jar
  2. 創建一個指向XML檔案的輸入流
    FileInputStream fis = new FileInputStream(“xml檔案的地址”);
  3. 創建一個XML讀取工具物件
    SAXReader sr = new SAXReader();
  4. 使用讀取工具物件, 讀取XML檔案的輸入流 , 并得到檔案物件
    Document doc = sr.read(fis);
  5. 通過檔案物件, 獲取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字串的步驟:

  1. 引入JAR包
  2. 在需要轉換JSON字串的位置撰寫如下代碼即可:
    String json = new Gson().toJSON(要轉換的物件);
    案例:
    Book b = BookDao.find();
    String json = new Gson().toJson(b);
    System.out.println(json);

將JSON字串轉換成物件:

  1. 引入JAR包
  2. 在需要轉換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;
}
}

  1. 概念定義在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 自定義注解名{}
注意事項

  1. 定義的注解,自動繼承了java.lang,annotation.Annotation介面
  2. 注解中的每一個方法,實際是宣告的注解配置引數
  3. 方法的名稱就是 配置引數的名稱
    方法的回傳值型別,就是配置引數的型別,只能是:基本型別/Class/String/enum
  4. 可以通過default來宣告引數的默認值
  5. 如果只有一個引數成員,一般引數名為value
  6. 注解元素必須要有值,我們定義注解元素時,經常使用空字串、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 中的類、介面或則物件的資訊,

  1. Class 類:反射的核心類,可以獲取類的屬性,方法等資訊,
  2. Field 類:Java.lang.reflec 包中的類,表示類的成員變數,可以用來獲取和設定類之中的屬性值,
  3. Method 類: Java.lang.reflec 包中的類,表示類的方法,它可以用來獲取類中的方法資訊或
    者執行方法,
  4. 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方法:

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

6.6 獲取Field

  1. getDeclaredField(String filedName)
    根據屬性的名稱, 獲取一個屬性物件 (所有屬性)
  2. getDeclaredFields()
    獲取所有屬性
  3. getField(String filedName)
    根據屬性的名稱, 獲取一個屬性物件 (public屬性)
  4. getFields()
    獲取所有屬性 (public)
    Field屬性的物件型別
    常用方法:
  5. get(Object o );
    引數: 要獲取屬性的物件
    獲取指定物件的此屬性值
  6. set(Object o , Object value);
    引數1. 要設定屬性值的 物件
    引數2. 要設定的值
    設定指定物件的屬性的值
  7. getName()
    獲取屬性的名稱
  8. 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

上一篇:阿里云RocketMQ定時/延遲訊息佇列實作

下一篇:Spring Boot系列(二)、Spring Boot初級應用及組態檔

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more