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 () 等等..

疑问解决。

最新文章

  1. eclipse导入cordova项目
  2. Avada主题通过自定义CSS全局更换微软雅黑字体
  3. C++ 检测内存泄露工具 -- Windows平台
  4. OpenJudge/Poj 1321 棋盘问题
  5. c语言中的结构体为值类型,当把一个结构体赋值给另一个结构体时,为值传递
  6. Java反射学习(java reflect)(三)
  7. 用ASP.net判断上传文件类型的三种方法
  8. springmvc 参数绑定
  9. Hadoop 安装(1) CENTOS 安装与配置
  10. eclipse快捷键说明
  11. jq,返回上一页,小记history.back(-1)和history.go(-1)区别
  12. C语言中的可变参数函数的浅析(以Arm 程序中的printf()函数实现为例) .
  13. 常用数据类型的方法--str、int、list、dict
  14. 为什么LINQ to XML的性能要优于XmlDocument?
  15. linux pidstat 命令详解
  16. PCM转MP3工具的封装
  17. DPHARD
  18. JSP语法学习笔记
  19. IdentityServer4实现单点登录统一认证
  20. bzoj3223 文艺平衡树 codevs3303 翻转区间

热门文章

  1. centos 6.4 源码安装php5.4 mysql5.5 apahce2
  2. Python生成器实现斐波那契数列
  3. [ZPG TEST 116] 最小边权和【生成树相关】
  4. 题解报告:hdu1202The calculation of GPA(算绩点问题)
  5. 加权平均值 WAvg”
  6. hadoop-2.4.1集群搭建及zookeeper管理
  7. NavigationView的使用
  8. CAS server 连接mysql的deployerConfigContext.xml配置
  9. JS 中的 JSON
  10. 一个圆的移动 AE教程 速度曲线调节