什么是抽象类和接口
抽象类:简而言之,用abstract关键词修饰的类就是抽象类,抽象类不能创建实例对象,即不能new对象。
接口:接口就是一种特殊的抽象类,接口中的所有方法都必须是抽象的且默认是public abstaract类型的。
接口的思想是什么
Java为什么在有了抽象类还需要提出接口?
因为抽象类依然没有摆脱类的概念,也就是说抽象类还必须由继承它的子类去实现抽象类中的抽象方法,本质上还是面向对象中的继承思想,而在现实世界中继承的关系虽然随处可见,但更多的思想是“对某种功能的实现“,比如客户提出我想要一个可以通信的工具,于是很多商家针对这种需求开发了对讲机,手机,固话等,可以明显的发现对讲机,手机,固话并不是对通信工具的继承,因为通信工具甚至没有一个具体的概念,也就是说它的抽象层次非常高,仅仅只是对”通信“这个功能的描述,而如果是传统的类就需要定义具体的属性,方法等。
所以,继面向对象后Java提出了面向接口编程,接口只定义模块之间的通信契约,而抽象类在代码实现方面发挥了具体作用,两者的应用范围是不一样的。
在jdk源码中随处可见的更多的是接口和抽象类,Java用接口的方式间接的实现了“多继承”,而声明接口创建实现类也是多态的一种体现。
public interface Signal{}
public SignalImpl implements Signal{}
public class Test(){
Signal signal = new SignalImpl();
}
深入两者的各种区别
1.抽象类可以有构造方法,接口中不能有。
2.抽象类中可以有普通成员变量,接口中不能有。
3.抽象类可以包含非抽象的普通方法,接口在jdk中也可以,但必须用default修饰方法。
public interface Test {
default int sum(int i,int j) {
return i * j;
}
}
但不推荐这么做,应该尽可能的写成
public interface Test {
int sum(int i,int j);
}
}
以供实现类去实现这个方法。
4.抽象类中的抽象方法的访问类型可以是public,protected,默认,但静态抽象方法不能是默认的,而接口默认即为public abstract。
5.抽象类中可以包含静态方法,但接口中不能包含静态方法。
6.抽象类和接口中都可以包含静态成员变量,抽象类中静态成员变量访问类型可以任意,但接口中定义的成员变量只能是public static final类型,并且默认如此。
7.一个类可以实现多个接口,但只能继承一个抽象类。
一个抽象类的经典应用
模板方法设计模式是抽象类的一个典型应用,假设某个项目中所有的Servlet类都要 用相同的方式进行权限判断,记录访问日志,异常处理,那么就可以定义一个抽象的基类,在抽象基类的service方法中完成所有的逻辑。
例如:
localhost:8080/store/productServlet?method=addProduct
我们可以在访问productServlet传入一个方法addProduct,定义一个BaseServlet继承自HttpServlet抽象类。
采用底层字节码技术就可以实现通用的逻辑设计
public class abstract BaseServlet extends HttpServlet {
@Override
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// localhost:8080/store/ProductServlet?method=findProductByPid&pid=1
String method = req.getParameter("method");
if (null == method || "".equals(method) || method.trim().equals("")) {
method = "execute";
}
Class clazz = this.getClass();
try {
Method md = clazz.getMethod(method, HttpServletRequest.class, HttpServletResponse.class);
if(null!=md){
String jspPath = (String)md.invoke(this, req, resp);
if (null != jspPath) {
req.getRequestDispatcher(jspPath).forward(req, resp);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 默认方法
public String execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
return null;
}
public class ProductServlet extends BaseServlet {
public String findProductByPid(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//获取商品pid
String pid = req.getParameter("pid");
//根据商品pid查询商品信息
IProductService prodectService = new ProductServiceImpl();
Product product = prodectService.findByProductByPid(pid);
//将获取到的商品放入request
req.setAttribute("product", product);
//转发/jsp/product_info.jsp
return "/jsp/product_info.jsp";
}
}
如此一来就不用直接继承自HttpServletRequest写大量的doGet,doPost方法,看起来就立马清爽了许多。