Java基礎之反射(非常重要)
點選上方“Java團長”,選擇“置頂公眾號”
技術文章第一時間送達!
反射是框架設計的靈魂
(使用的前提條件:必須先得到代表的位元組碼的Class,Class類用於表示.class檔案(位元組碼))
一、反射的概述
JAVA反射機制是在執行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個物件,都能夠呼叫它的任意一個方法和屬性;這種動態獲取的資訊以及動態呼叫物件的方法的功能稱為java語言的反射機制。
要想解剖一個類,必須先要獲取到該類的位元組碼檔案物件。而解剖使用的就是Class類中的方法.所以先要獲取到每一個位元組碼檔案對應的Class型別的物件.
以上的總結就是什麼是反射
反射就是把java類中的各種成分對映成一個個的Java物件
例如:一個類有:成員變數、方法、構造方法、包等等資訊,利用反射技術可以對一個類進行解剖,把個個組成部分對映成一個個物件。
(其實:一個類中這些成員方法、構造方法、在加入類中都有一個類來描述)
如圖是類的正常載入過程:反射的原理在與class物件。
熟悉一下載入的時候:Class物件的由來是將class檔案讀入記憶體,併為之建立一個Class物件。
其中這個Class物件很特殊。我們先了解一下這個Class類
二、檢視Class類在java中的api詳解(1.7的API)
如何閱讀java中的api詳見java基礎之——String字串處理
Class
類的例項表示正在執行的 Java 應用程式中的類和介面。也就是jvm中有N多的例項每個類都有該Class物件。(包括基本資料型別)
Class
沒有公共構造方法。Class
物件是在載入類時由 Java 虛擬機器以及通過呼叫類載入器中的defineClass
方法自動構造的。也就是這不需要我們自己去處理建立,JVM已經幫我們建立好了。
沒有公共的構造方法,方法共有64個太多了。下面用到哪個就詳解哪個吧
三、反射的使用(這裡使用Student類做演示)
先寫一個Student類。
1、獲取Class物件的三種方式
1.1 Object ——> getClass();
1.2 任何資料型別(包括基本資料型別)都有一個“靜態”的class屬性
1.3 通過Class類的靜態方法:forName(String className)(常用)
其中1.1是因為Object類中的getClass方法、因為所有類都繼承Object類。從而呼叫Object類來獲取
<span style="font-size:18px;">package fanshe;
/**
* 獲取Class物件的三種方式
* 1 Object ——> getClass();
* 2 任何資料型別(包括基本資料型別)都有一個“靜態”的class屬性
* 3 通過Class類的靜態方法:forName(String className)(常用)
*
*/
public class Fanshe {
public static void main(String[] args) {
//第一種方式獲取Class物件
Student stu1 = new Student();//這一new 產生一個Student物件,一個Class物件。
Class stuClass = stu1.getClass();//獲取Class物件
System.out.println(stuClass.getName());
//第二種方式獲取Class物件
Class stuClass2 = Student.class;
System.out.println(stuClass == stuClass2);//判斷第一種方式獲取的Class物件和第二種方式獲取的是否是同一個
//第三種方式獲取Class物件
try {
Class stuClass3 = Class.forName("fanshe.Student");//注意此字串必須是真實路徑,就是帶包名的類路徑,包名.類名
System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個Class物件
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}</span>
注意:在執行期間,一個類,只有一個Class物件產生。
三種方式常用第三種,第一種物件都有了還要反射干什麼。第二種需要匯入類的包,依賴太強,不導包就拋編譯錯誤。一般都第三種,一個字串可以傳入也可寫在配置檔案中等多種方法。
2、通過反射獲取構造方法並使用:
student類:
package fanshe;
public class Student {
//---------------構造方法-------------------
//(預設的構造方法)
Student(String str){
System.out.println("(預設)的構造方法 s = " + str);
}
//無參構造方法
public Student(){
System.out.println("呼叫了公有、無參構造方法執行了。。。");
}
//有一個引數的構造方法
public Student(char name){
System.out.println("姓名:" + name);
}
//有多個引數的構造方法
public Student(String name ,int age){
System.out.println("姓名:"+name+"年齡:"+ age);//這的執行效率有問題,以後解決。
}
//受保護的構造方法
protected Student(boolean n){
System.out.println("受保護的構造方法 n = " + n);
}
//私有構造方法
private Student(int age){
System.out.println("私有的構造方法 年齡:"+ age);
}
}
共有6個構造方法;
測試類:
package fanshe;
import java.lang.reflect.Constructor;
/*
* 通過Class物件可以獲取某個類中的:構造方法、成員變數、成員方法;並訪問成員;
*
* 1.獲取構造方法:
* 1).批量的方法:
* public Constructor[] getConstructors():所有"公有的"構造方法
public Constructor[] getDeclaredConstructors():獲取所有的構造方法(包括私有、受保護、預設、公有)
* 2).獲取單個的方法,並呼叫:
* public Constructor getConstructor(Class... parameterTypes):獲取單個的"公有的"構造方法:
* public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個構造方法"可以是私有的,或受保護、預設、公有;
*
* 呼叫構造方法:
* Constructor-->newInstance(Object... initargs)
*/
public class Constructors {
public static void main(String[] args) throws Exception {
//1.載入Class物件
Class clazz = Class.forName("fanshe.Student");
//2.獲取所有公有構造方法
System.out.println("**********************所有公有構造方法*********************************");
Constructor[] conArray = clazz.getConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("************所有的構造方法(包括:私有、受保護、預設、公有)***************");
conArray = clazz.getDeclaredConstructors();
for(Constructor c : conArray){
System.out.println(c);
}
System.out.println("*****************獲取公有、無參的構造方法*******************************");
Constructor con = clazz.getConstructor(null);
//1>、因為是無參的構造方法所以型別是一個null,不寫也可以:這裡需要的是一個引數的型別,切記是型別
//2>、返回的是描述這個無參建構函式的類物件。
System.out.println("con = " + con);
//呼叫構造方法
Object obj = con.newInstance();
// System.out.println("obj = " + obj);
// Student stu = (Student)obj;
System.out.println("******************獲取私有構造方法,並呼叫*******************************");
con = clazz.getDeclaredConstructor(char.class);
System.out.println(con);
//呼叫構造方法
con.setAccessible(true);//暴力訪問(忽略掉訪問修飾符)
obj = con.newInstance('男');
}
}
後臺輸出:
**********************所有公有構造方法*********************************
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
************所有的構造方法(包括:私有、受保護、預設、公有)***************
private fanshe.Student(int)
protected fanshe.Student(boolean)
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
fanshe.Student(java.lang.String)
*****************獲取公有、無參的構造方法*******************************
con = public fanshe.Student()
呼叫了公有、無參構造方法執行了。。。
******************獲取私有構造方法,並呼叫*******************************
public fanshe.Student(char)
姓名:男
呼叫方法:
1.獲取構造方法:
1).批量的方法:
public Constructor[] getConstructors():所有"公有的"構造方法
public Constructor[] getDeclaredConstructors():獲取所有的構造方法(包括私有、受保護、預設、公有)
2).獲取單個的方法,並呼叫:
public Constructor getConstructor(Class... parameterTypes):獲取單個的"公有的"構造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個構造方法"可以是私有的,或受保護、預設、公有;
呼叫構造方法:
Constructor-->newInstance(Object... initargs)
2、newInstance是 Constructor類的方法(管理建構函式的類)
api的解釋為:
newInstance(Object... initargs)
使用此 Constructor
物件表示的構造方法來建立該構造方法的宣告類的新例項,並用指定的初始化引數初始化該例項。
它的返回值是T型別,所以newInstance是建立了一個構造方法的宣告類的新例項物件。併為之呼叫
3、獲取成員變數並呼叫
student類:
<span style="font-size:14px;">package fanshe.field;
public class Student {
public Student(){
}
//**********欄位*************//
public String name;
protected int age;
char sex;
private String phoneNum;
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + ", sex=" + sex
+ ", phoneNum=" + phoneNum + "]";
}
}</span>
測試類:
<span style="font-size:14px;">package fanshe.field;
import java.lang.reflect.Field;
/*
* 獲取成員變數並呼叫:
*
* 1.批量的
* 1).Field[] getFields():獲取所有的"公有欄位"
* 2).Field[] getDeclaredFields():獲取所有欄位,包括:私有、受保護、預設、公有;
* 2.獲取單個的:
* 1).public Field getField(String fieldName):獲取某個"公有的"欄位;
* 2).public Field getDeclaredField(String fieldName):獲取某個欄位(可以是私有的)
*
* 設定欄位的值:
* Field --> public void set(Object obj,Object value):
* 引數說明:
* 1.obj:要設定的欄位所在的物件;
* 2.value:要為欄位設定的值;
*
*/
public class Fields {
public static void main(String[] args) throws Exception {
//1.獲取Class物件
Class stuClass = Class.forName("fanshe.field.Student");
//2.獲取欄位
System.out.println("************獲取所有公有的欄位********************");
Field[] fieldArray = stuClass.getFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("************獲取所有的欄位(包括私有、受保護、預設的)********************");
fieldArray = stuClass.getDeclaredFields();
for(Field f : fieldArray){
System.out.println(f);
}
System.out.println("*************獲取公有欄位**並呼叫***********************************");
Field f = stuClass.getField("name");
System.out.println(f);
//獲取一個物件
Object obj = stuClass.getConstructor().newInstance();//產生Student物件--》Student stu = new Student();
//為欄位設定值
f.set(obj, "劉德華");//為Student物件中的name屬性賦值--》stu.name = "劉德華"
//驗證
Student stu = (Student)obj;
System.out.println("驗證姓名:" + stu.name);
System.out.println("**************獲取私有欄位****並呼叫********************************");
f = stuClass.getDeclaredField("phoneNum");
System.out.println(f);
f.setAccessible(true);//暴力反射,解除私有限定
f.set(obj, "18888889999");
System.
相關推薦
Java基礎之—反射(非常重要)
package fanshe;
import java.lang.reflect.Constructor;
/*
* 通過Class物件可以獲取某個類中的:構造方法、成員變數、成員方法;並訪問成員;
*
* 1.獲取構造方法:
* 1).批量的方法:
* public Constr
Java基礎之反射(非常重要)
點選上方“Java團長”,選擇“置頂公眾號”技術文章第一時間送達!反射是框架設計的靈魂(使用的前
Java基礎之反射應用(如何獲取物件的構造方法、屬性以及、基本方法)
反射實戰:新建Student類,利用反射原理輸出Student的構造方法,屬性,普通方法,引數列表等等資訊。
反射資料:查詢java_API之:java.lang.reflect包下。
Student類:
package com.briup.ch24;
public class St
Java基礎之反射例項(例項化Account與修改屬性)
要求:
設計Account類,並且新增屬性id、name、balance,新增get和set方法與存取錢的方法。
設計ReflectAccountTest類,例項化Account物件,存如100元,與取1000元的結果顯示。
&nb
Java基礎之Freemarker(1)模板加載及清空機制
ron date java 自帶 pda 直接 onf 刷新方法 希望 一 freemarker加載模版機制
freemarker中的配置項template_update_delay表明模版的緩存時間,單位是s,超過緩存時間則從磁盤加載最新的模版,具體細節如下:
1)fre
java基礎之--註解(一)
最近學習spring5的時候,發現好像多了一些新的註解,於是乎想好好看看這些註解到底是怎麼實現的,但是奈何自己連基礎的元註解都還是一知半解,所以還是萬丈高樓平地起,一切以基礎為重。下面就來說說jdk自帶的元註解,與新手朋友們分享也為自己填一個坑。
1.什麼是元
JAVA基礎之檔案(File)
File類
構造: public class File extends Object implements Serializable, Comparable File類就是檔案和目錄路徑名的抽象表示形式。 通過將給定路徑名字串轉換為抽象路徑名來建立一個新 File 例項,也就
Java基礎之引用(String,char[],Integer)總結於牛客網的專項練習題
1、String的引用:下列程式碼執行後的結果為:public class Test {
public static void main(String[] args) {
StringBuffe
Java基礎之異常(Exception)
異常,是Java中非常常用的功能,它可以簡化程式碼,並且增強程式碼的安全性。本文將介紹一些異常高階知識,也是學習Java一來的一次總結。包括以下內內容:
異常的基礎知識
異常特點
異常誤用
如何正確地使用異常
異常的實現原理
關於異常
異常機制,是
Java基礎部分回顧(為自己)
.cn logs -1 繼續 分享 9.png 沒有 理解 開始 最近,學到集合框架。感覺有些蒙圈兒。知道這一塊很重要很重要,不敢疏忽。自學遇到的攔路虎,想著是不是前面的基礎知道還沒有夯實,對一些概念沒有真正的理解到位呢?!所以,停下來。開始找一些視頻,做一下回顧。
再次鞏
Java基礎之反射
實例 編譯 ring 反序列化 ons 信息 method api 反射 Java反射是指運行時獲取類信息,進而在運行時動態構造對象、調用對象方法及修改對象屬性的機制。百度百科的定義:“JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和
Java學習之路(書籍推薦)
個人 分布式 方法 都是 操作 測試 對象 web編程 數據庫 一、基礎類
1、《Thinking in java》(閱讀2遍),入門第一位是建立正確的概念
2、《Core Java》這本書更貼近實踐,更多API的介紹,同樣,更新也更頻繁。(可以選重點章節讀一下)
二、進階
java基礎73 待續(網頁知識)
bsp 說明 http col tro font -s .cn java基礎 1、待續
待續
原創作者:DSHORE
作者主頁:http://www.cnblogs.com/dshore123/
原文出自:https://www.cnbl
面向對象之反射(定制)
租房子 click span 領域 面向 屬性和方法 lsd 正在 ttr 什麽是反射?
反射的蓋面是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省),
這一概念的提出很快引發了計算機科學領域關於應用反射的研究。它首
java基礎學習總結(二十三):什麼要使用AOP
從最基礎的原始程式碼-->使用設計模式(裝飾器模式與代理)-->使用AOP三個層次來講解一下為什麼我們要使用AOP。
原始程式碼的寫法
既然要通過程式碼來演示,那必須要有例子,這裡我的例子為:
有一個介面Dao有insert、delete、update三個方法,在insert
java基礎學習總結(二十):多執行緒上下文切換
什麼是上下文切換
即使是單核CPU也支援多執行緒執行程式碼,CPU通過給每個執行緒分配CPU時間片來實現這個機制。時間片是CPU分配給各個執行緒的時間,因為時間片非常短,所以CPU通過不停地切換執行緒執行,讓我們感覺多個執行緒時同時執行的,時
java基礎學習總結(十九):Unsafe與CAS
Unsafe
簡單講一下這個類。Java無法直接訪問底層作業系統,而是通過本地(native)方法來訪問。不過儘管如此,JVM還是開了一個後門,JDK中有一個類Unsafe,它提供了硬體級別的原子操作。
&n
java基礎學習總結(十八):切勿用普通for迴圈遍歷LinkedList
ArrayList與LinkedList的普通for迴圈遍歷
對於大部分Java程式設計師朋友們來說,可能平時使用得最多的List就是ArrayList,對於ArrayList的遍歷,一般用如下寫法:
public static void main(String[] args)
{
java基礎學習總結(十七):Java Socket
一、 什麼是Socket
Socket的概念很簡單,它是網路上執行的兩個程式間雙向通訊的一端,既可以接收請求,也可以傳送請求,利用它可以較為方便地編寫網路上資料的傳遞。
所以簡而言之,Socket就是程序通訊的端點
java基礎學習總結(十六):程式碼優化
程式碼優化的目標是:
1、減小程式碼的體積
2、提高程式碼執行的效率
程式碼優化細節
(1)儘量指定類、方法的final修飾符
帶有final修飾符的類是不可派生的。在Java核心API中,有許多應用final的例子,例如java.lang.Strin