1. 程式人生 > >關於Filter中ServletRequest強轉HttpServletRequest問題

關於Filter中ServletRequest強轉HttpServletRequest問題

htm net 類的方法 interface public 類型轉換 是我 執行 問題解決

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;

}

因為要用到HttpServletRequest中的方法,我對ServletRequest進行了強轉,然後問題解決。可是後來一想不對啊,我們知道我們對子類實現進行向上轉型得到父類對象是安全的,因為子類會完全繼承父類的方法,我們向上轉型為父類,當我們調用父類的方法其實在子類實現中是能完全找到的。反之向下轉型是不安全的,我們子類除了完全繼承父類的方法外還會拓展自己的方法,所以我們在調用子類方法時可能在父類實現中是找不到的,所以向下轉型不安全。

可是本例中的實現卻讓我們困惑,我們不僅實現了向下轉型,同時還調用了子類拓展的方法,是父類沒有的,可是卻實現了。這不是和我們所學矛盾嗎?後來看了API和一些資料我終於明白了,這和我們所學其實並不沖突!我們先看API:

public interface HttpServletRequest extends ServletRequest

終於找到原因了,原來HttpServletRequest和ServletRequest都是接口,他們都只是定義了方法卻沒有提供相關實現。所以我們看到的ServletRequest request中的request對象其實並不是我們ServletRequest 的一個具體實現。

這裏我們要看我們提出的問題是否安全,其實主要看request 對象的具體實現類究竟是繼承的哪個接口,如果繼承自HttpServletRequest接口那麽我們向下轉型使用HttpServletRequest接口的方法就是安全的。測試如下:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if(request instanceof HttpServletRequest){
System.out.println("-------------");
}
HttpServletRequest req = (HttpServletRequest) request;
if(req instanceof HttpServletRequest){
      System.out.println("我是右邊類的實例");
}
HttpServletResponse resp = (HttpServletResponse) response;
}

輸出:

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

 我是右邊類的實例

證明我們的request對象的確是HttpServletRequest的一個實例。

 也就是說doFilter的參數request對象的生成方式不是ServletRequest request = new ServletRequest();這種形式,而是ServletRequest request = new HttpServletRequest();這種形式,參數裏的request不是父類ServletRequest的對象,而是HttpServletRequest的上轉型對象:

  根據《java面向對象程序設計(第2版)》,一個父類類型的對象如果是用子類new出來的時候(ServletRequest request = new HttpServletRequest();//就是這行代碼), 就不能稱之為父類對象,而是一個子類的上轉型對象。這兩者是有區別的,區別的其中一點就是父類對象不可強制轉換為子類對象,而子類的上轉型對象可以強制轉換回子類對象。

  再說一下為什麽在Filter裏要強制轉換?

  答:ServletRequest request;這個是將子類對象賦給父類引用,他運行時的類型是子類,編譯時的類型是父類,但是在運行時,父類類型對象調用的方法如果子類裏面有,那就執行子類裏面的方法,如果編譯時的類型也就是父類沒有調用的那個方法,則報錯。所以在那裏要做一個強制類型轉換,否則就會報錯。

HttpServletRequest比ServletRequest多了一些針對於Http協議的方法.如getHeader (String name), getMethod () ,getSession () 等等..

疑問解決。

關於Filter中ServletRequest強轉HttpServletRequest問題