1. 程式人生 > >第11篇 Java反射/正則表示式

第11篇 Java反射/正則表示式

反射技術:其實就是動態載入一個指定的類,並獲取該類中的所有的內容。而且將位元組碼檔案封裝成物件,並將位元組碼檔案中的內容都封裝成物件,這樣便於操作這些成員。簡單說:反射技術可以對一個類進行解剖。

 

反射的好處:大大的增強了程式的擴充套件性。

 

反射的基本步驟:

1、獲得Class物件,就是獲取到指定的名稱的位元組碼檔案物件。

2、例項化物件,獲得類的屬性、方法或建構函式。

3、訪問屬性、呼叫方法、呼叫建構函式建立物件。

 

獲取這個Class物件,有三種方式:

1:通過每個物件都具備的方法getClass來獲取。弊端:必須要建立該類物件,才可以呼叫getClass方法。

2:每一個數據型別(基本資料型別和引用資料型別)都有一個靜態的屬性class。弊端:必須要先明確該類。

 前兩種方式不利於程式的擴充套件,因為都需要在程式使用具體的類來完成。

3:使用的Class類中的方法,靜態的forName方法

 指定什麼類名,就獲取什麼類位元組碼檔案物件,這種方式的擴充套件性最強,只要將類名的字串傳入即可。

// 1. 根據給定的類名來獲得  用於類載入

String classname = "cn.itcast.reflect.Person";// 來自配置檔案

Class clazz = Class.forName

(classname);// 此物件代表Person.class

// 2. 如果拿到了物件,不知道是什麼型別   用於獲得物件的型別

Object obj = new Person();

Class clazz1 = obj.getClass();// 獲得物件具體的型別

// 3. 如果是明確地獲得某個類的Class物件  主要用於傳參

Class clazz2 = Person.class;

 

反射的用法

1)、需要獲得java類的各個組成部分,首先需要獲得類的Class物件,獲得Class物件的三種方式:

Class.forName(classname)

用於做類載入

obj.getClass() 用於獲得物件的型別

類名.class     用於獲得指定的型別,傳參用

 

2)、反射類的成員方法:

Class clazz = Person.class;

Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2});

method.invoke();

 

3)、反射類的建構函式:

Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...})

con.newInstance(params...)

 

4)、反射類的屬性:

Field field = clazz.getField(fieldName);

field.setAccessible(true);

field.setObject(value);

 

獲取了位元組碼檔案物件後,最終都需要建立指定類的物件:

建立物件的兩種方式(其實就是物件在進行例項化時的初始化方式):

1,呼叫空引數的建構函式:使用了Class類中的newInstance()方法。

2,呼叫帶引數的建構函式:先要獲取指定引數列表的建構函式物件,然後通過該建構函式的物件的newInstance(實際引數) 進行物件的初始化。

 

綜上所述,第二種方式,必須要先明確具體的建構函式的引數型別,不便於擴充套件。所以一般情況下,被反射的類,內部通常都會提供一個公有的空引數的建構函式。

------------------------------------------------------

// 如何生成獲取到位元組碼檔案物件的例項物件。

Class clazz = Class.forName("cn.itcast.bean.Person");//類載入

// 直接獲得指定的型別

clazz = Person.class;

// 根據物件獲得型別

Object obj = new Person("zhangsan", 19);

clazz = obj.getClass();

 

Object obj = clazz.newInstance();//該例項化物件的方法呼叫就是指定類中的空引數建構函式,給建立物件進行初始化。當指定類中沒有空引數建構函式時,該如何建立該類物件呢?請看method_2();

public static void method_2() throws Exception {

Class clazz = Class.forName("cn.itcast.bean.Person");

//既然類中沒有空引數的建構函式,那麼只有獲取指定引數的建構函式,用該函式來進行例項化。

//獲取一個帶引數的構造器。

Constructor constructor = clazz.getConstructor(String.class,int.class);

//想要對物件進行初始化,使用構造器的方法newInstance();

Object obj = constructor.newInstance("zhagnsan",30);

//獲取所有構造器。

Constructor[] constructors = clazz.getConstructors();//只包含公共的

constructors = clazz.getDeclaredConstructors();//包含私有的

for(Constructor con : constructors) {

System.out.println(con);

}

}

------------------------------------------------------

反射指定類中的方法:

//獲取類中所有的方法。

public static void method_1() throws Exception {

Class clazz = Class.forName("cn.itcast.bean.Person");

Method[] methods = clazz.getMethods();//獲取的是該類中的公有方法和父類中的公有方法。

methods = clazz.getDeclaredMethods();//獲取本類中的方法,包含私有方法。

for(Method method : methods) {

System.out.println(method);

}

}

//獲取指定方法;

public static void method_2() throws Exception {

Class clazz = Class.forName("cn.itcast.bean.Person");

//獲取指定名稱的方法。

Method method = clazz.getMethod("show", int.class,String.class);

//想要執行指定方法,當然是方法物件最清楚,為了讓方法執行,呼叫方法物件的invoke方法即可,但是方法執行必須要明確所屬的物件和具體的實際引數。

Object obj = clazz.newInstance();

method.invoke(obj, 39,"hehehe");//執行一個方法

}

//想要執行私有方法。

public static void method_3() throws Exception {

Class clazz = Class.forName("cn.itcast.bean.Person");

//想要獲取私有方法。必須用getDeclearMethod();

Method method = clazz.getDeclaredMethod("method", null);

// 私有方法不能直接訪問,因為許可權不夠。非要訪問,可以通過暴力的方式。

method.setAccessible(true);//一般很少用,因為私有就是隱藏起來,所以儘量不要訪問。

}

//反射靜態方法。

public static void method_4() throws Exception {

Class clazz = Class.forName("cn.itcast.bean.Person");

Method method = clazz.getMethod("function",null);

method.invoke(null,null);

}

 

正則表示式:★★★☆,其實是用來操作字串的一些規則。

好處:正則的出現,對字串的複雜操作變得更為簡單。

特點:將對字串操作的程式碼用一些符號來表示。只要使用了指定符號,就可以呼叫底層的程式碼對字串進行操作。符號的出現,簡化了程式碼的書寫。

弊端:符號的出現雖然簡化了書寫,但是卻降低了閱讀性。

其實更多是用正則解決字串操作的問題。

 

組:用小括號標示,每定義一個小括號,就是一個組,而且有自動編號,從1開始。

只要使用組,對應的數字就是使用該組的內容。別忘了,陣列要加\\。

(aaa(wwww(ccc))(eee))技巧,從左括號開始數即可。有幾個左括號就是幾組。

 

常見操作:

1,匹配:其實用的就是String類中的matches方法。

String reg = "[1-9][0-9]{4,14}";

boolean b = qq.matches(reg);//將正則和字串關聯對字串進行匹配。

2,切割:其實用的就是String類中的split方法。

3,替換:其實用的就是String類中的replaceAll();

4,獲取:

   1),先要將正則表示式編譯成正則物件。使用的是Pattern中靜態方法 compile(regex);

2),通過Pattern物件獲取Matcher物件。

Pattern用於描述正則表示式,可以對正則表示式進行解析。

而將規則操作字串,需要從新封裝到匹配器物件Matcher中。

然後使用Matcher物件的方法來操作字串。

如何獲取匹配器物件呢?

通過Pattern物件中的matcher方法。該方法可以正則規則和字串想關聯。並返回匹配器物件。

3),使用Matcher物件中的方法即可對字串進行各種正則操作。