Java反射----reflect.
String action = request.getParameter("action");
try {
Class clazz = this.getClass();
Class[] pTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };// 創建方法的參數類型
Method method = clazz.getMethod(action, pTypes);
method.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
}
這個機制允許運行中的程序“自省”,也可以說“自審”。
這種機制主要運用於開發者自己編寫框架供其他開發人員進行二次開發。
利用reflect可以動態調用java類(對象)中的方法和屬性,既然是調用就要有方法。
在這裏需要用到 Class和Method這兩個類。
利用Class中的 **.forName("***")、**.getClass()等方法得到所需類的對象,由於需要調用某個方法,爲了避免重載的函數導致混亂的調用就一定需要知道該方法的參數類型,這樣就利用
例如:Class[] pTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class }
設置需要的參數類型的數組。現在,就該用到Method這個類了,實例化一個Method類的對象,利用之前回去的所需類的對象調用**.getMethod(action, pTypes);這個方法,並將所需的參數值和參數類型傳入進去。
最後就需要利用到Method中的
method.invoke(this, request, response);來調用 this 對象下的 形參值爲 request和response的方法
在Servlet中使用Java反射機制
Servlet的生命週期
每個Servlet文件都必須繼承HttpServlet類,在Servlet底層的運行機制中,需要先運行init方法,用於初始化一下操作。
然後執行service方法,在service方法中將會判斷請求是get方式的還是post方式的,然後自動執行相對應的 doGet()方法或
doPost()方法。
這樣,只要寫一個公共的BaseServlet文件,將service方法重寫,然後在每個Servlet中繼承這個BaseServlet文件,即
可省去在每個Servlet中都需要寫的doGet()方法和doPost()方法,減少了代碼量,又增加的程序的可讀性。
//BaseServlet.java
public class BaseServlet extends HttpServlet {
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
//action = doLogin;
try {
Class clazz = this.getClass();
Class[] pTypes = new Class[] { HttpServletRequest.class, HttpServletResponse.class };
Method method = clazz.getMethod(action, pTypes);
method.invoke(this, request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
}
並且,這樣可以省去很多的if else判斷來確定需要調用的方法。
Pay attention!
注意:
爲什麼執行每個Servlet文件都會先執行BaseServlet中的service方法呢?
這就涉及到面向對象中多態方面的知識點了。
例如
public class A{
public void A(){
System.out.println("A...");
}
public void C(){
System.out.println("A...C");
}
}
public class B extends A{
public void B(){
System.out.println("B...");
}
public void C(){
System.out.println("B...C");
}
}
public class Test{
B b = new B();
b.C();
}
在這個例子中,創建了一個B類的對象,那麼會得到什麼樣的輸出呢?
A...
B...
這樣就可以得出一個結論,就是:
如果一個類(子類)繼承到另外一個類(父類),那麼在創建一個子類的對象的時候,系統會自動爲你創建一個父類的對象,所以一定會先調用父類的構造方法,然後再調用子類的構造方法。
用一個通俗的方法解釋就是: 沒有爸爸,哪來的兒子呢?
接下來 b.C()會輸出什麼呢?
B...C
我們可以得出的另外一個結論就是:
如果子類中有和父類重名的方法,那麼在創建的子類對象調用該方法的時候,調用的是子類的方法,而不是父類的方法。