一文讲透抽象类和接口

什么是抽象类和接口

抽象类:简而言之,用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.抽象类可以包含非抽象的普通方法,虽然接口在jdk1.8中也可以,但必须用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.抽象类中可以包含静态方法,但接口中不能包含静态方法。
PS:为什么呢?

因为java 中不能定义抽象静态方法static
interface中所有的成员方法都是abstract的,当然也就不能定义静态方法static。
如果可以定义抽象静态方法static,设 static abstract method(); 是抽象类A的方法
那么因为是静态方法,所以可以用类名.method();来调用
而这个方法又是抽象的没有方法体,调用了怎么执行呢?

6.抽象类和接口中都可以包含静态成员变量,抽象类中静态成员变量访问类型可以任意,但接口中定义的成员变量只能是public static final类型,并且默认如此。

7.一个类可以实现多个接口,但只能继承一个抽象类。

一个抽象类的经典应用

模板方法设计模式是抽象类的一个典型应用,假设某个项目中所有的Servlet类都要用相同的方式进行权限判断,记录访问日志,异常处理,那么就可以定义一个抽象的基类,在抽象基类的service方法中完成所有的逻辑。

例如:

localhost:8080/store/ProductServlet?method=findProductByPid&pid=1

我们可以在访问productServlet传入一个方法findProductByPid,定义一个抽象类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方法,看起来就立马清爽了许多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值