原来你是这样的JAVA[03]-继承、多态、抽象类
一、继承
Java中的继承使用关键字extends ,跟C#的语法略有差别。
1.子类构造器
java会自动在子类的构造器中插入对父类构造器的调用,也就是说在子类可以访问父类之前已经完成了父类的初始化。
如果想调用带参数的父类构造器,应该使用super关键字。
/**
* @author 陈敬
* @date 18/1/17
*/
public class Product {
private String name; public Product(String name) {
this.name = name;
System.out.println("[Product constructor]");
}
} public class Bread extends Product {
private int price; public Bread(String name, int price) {
super(name);//调用父类构造器
this.price = price;
System.out.println("[Bread constructor]");
}
}
我们创建一个Bread类的实例,看看调用顺序。
@Test
public void testConstructor(){
Bread bread=new Bread("毛毛虫面包",10);
}
打印结果:
[Product constructor]
[Bread constructor]
2.调用父类方法
子类是不能直接访问到父类的私有域的,如果想访问只能借助父类公开的get访问器。子类调用父类中的方法也需要使用super关键字。
public class Product {
private String name;
public String getName() {
return name;
}
public Product(String name) {
this.name = name;
}
}
public class Bread extends Product {
public Bread(String name) {
super(name);
}
public void display(){
System.out.println(getName());
}
}
然后写个单元测试:
@Test
public void testPrivate(){
Bread bread=new Bread("毛毛虫面包");
bread.display();//毛毛虫面包
}
需要说明一点,super并不是一个对象的引用,不能将super赋值给变量,它只是一个特殊的关键字,告诉编辑器要调用父类中的方法。
3.关于重载
如果父类中存在重载方法,子类又进行了重载,会覆盖父类中的方法吗?实际上,父类和子类中的方法都可以正常重载,不会被覆盖。
首先在父类Product中添加方法getDescription():
public class Product {
……
public String getDescription() {
return "[Product]name="+name;
}
}
然后在子类中重载该方法:
public class Bread extends Product {
……
public String getDescription(String storeName) {
return "[Bread]storename="+storeName;
}
}
增加一个单元测试:
public class ExtendClassTests {
@Test
public void testOverload(){
Bread bread=new Bread("豆沙面包",9);
System.out.println(bread.getDescription());
System.out.println(bread.getDescription("味多美"));
}
}
输出:
[Product]name=豆沙面包
[Bread]storename=味多美
4.继承准则
继承准则:尽量少用继承。一般用继承表达行为间的差异,用组合表示状态上的变化。
二、多态
1.变量多态
在Java中对象变量是多态的,一个Product变量可以引用Product对象,也可以引用一个Product子类的对象。
@Test
public void testParent(){
Product product=new Bread("毛毛虫面包",10);
product.display();
//强制类型转换
if(product instanceof Bread){
Bread brand=(Bread)product;
brand.display("味多美");
}
}
由于Bread实例向上转型为Product类型,所以不能再调用Bread.getDescription(String storeName)方法。
如果需要将父类强制转换为子类时,要先通过instanceof检测对象类型,我们最好尽量避免使用强制类型转换。
2.动态绑定
所谓动态绑定,就是在运行时根据对象的类型决定要调用的方法。在java中,动态绑定是默认行为,不需要添加额外的关键字实现多态。
再写个demo来看一下,在父类和子类中重载了display方法。
public class Product {
private String name;
public Product(String name) {
this.name = name;
}
public void display() {
System.out.println("[Product]getDescription()");
}
}
public class Bread extends Product {
private int price;
public Bread(String name, int price) {
super(name);
this.price = price;
}
@Override
public void display() {
System.out.println("[Bread]getDescription()");
}
public void display(String storeName) {
System.out.println("[Bread]getDescription(String storeName)");
}
}
添加单元测试:
@Test
public void dynamicBind(){
Product product=new Product("product");
product.display(); //[Product]getDescription() Bread bread=new Bread("毛毛虫",9);
bread.display(); //[Bread]getDescription()
bread.display("maimai"); //[Bread]getDescription(String storeName) Product product1=bread;
product1.display(); //[Bread]getDescription()
}
虚拟机为每个类创建一个方法表,列出所有方法的签名和实际调用的方法。这样一来,当动态调用方法的时候,只需要查找方法表就能快速的找到真正调用的方法了。
Product:
display()->Product.display()
Bread:
display()->Bread.display()
display(String name)->Bread.display(String name)
完整源码参见:https://github.com/cathychen00/cathyjava /_08_extend
三、抽象类
定义抽象方法用用abstract关键字,它仅有声明而没有方法体。
包含抽象方法的类叫做抽象类,如果一个类包含一个或多个抽象方法,那么必须被定义为抽象类。
如果一个类从抽象类继承,那么必须为抽象类中的所有抽象方法提供实现,否则该类也必须被定义为抽象类。
看一个场景:我们有一些定时任务,要进行的工作流程类似,只有具体一部分细节内容不同。我们可以定义一个抽象基类BaseJob,再不同的部分封装为抽象方法,具体的实现在子类中进行。
public abstract class BaseJob {
public void run(){
System.out.println("==START "+getDescription()+"==");
String lastJobId=getLastJobId();
execute(lastJobId);
writeLog();
System.out.println("==END "+getDescription()+"==");
}
protected abstract String getDescription();
protected abstract void execute(String jobId);
private void writeLog() {
System.out.println("write log to DB");
}
private String getLastJobId() {
return "job1221";
}
}
public class ArticleJob extends BaseJob {
@Override
protected String getDescription() {
return "抓取文章任务";
}
@Override
protected void execute(String jobId) {
System.out.println("抓取站点新闻文章 jobid="+jobId);
}
public static void main(String[] args) {
BaseJob articleJob=new ArticleJob();
articleJob.run();
}
}
创建单元测试,调用ArticleJob看看。
@Test
public void articleJob(){
BaseJob articleJob=new ArticleJob();
articleJob.run();
}
运行结果:
==START 抓取文章任务==
抓取站点新闻文章 jobid=job1221
write log to DB
==END 抓取文章任务==
当再次添加符合该流程的定时任务时,只需要新建一个类,实现BaseJob就可以了。
完整例子:https://github.com/cathychen00/cathyjava /09_abstract
原来你是这样的JAVA[03]-继承、多态、抽象类的更多相关文章
- Java开发知识之Java的继承多态跟接口*
Java开发知识之Java的继承多态跟接口 一丶继承 1.继承的写法 在Java中继承的 关键字是 extends 代表一个类继承另一个类. 继承的含义以及作用: 继承就是基于某个父类的扩展.制定出来 ...
- Java 封装 继承 多态
Java 继承 继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法 ...
- Java之继承和抽象类
继承 继承的实现 继承通过extends实现 格式:class 子类 extends 父类 { } 举例:class Dog extends Animal { } 继承带来的好处 继承可以让类与类 ...
- java 接口 继承 接口 抽象类 继承 实体类
韩梦飞沙 韩亚飞 313134555@qq.com yue31313 han_meng_fei_sha 接口 可以 继承 接口 抽象类 可以 实现 接口 抽象类 继承实体类 需要 实体类 有 ...
- Java之继承、抽象类、接口篇
一.继承(extends) 什么是继承? 继承是对现实生活中的"分类"概念的一种模拟. 狮子拥有动物的一切基本特性,但同时又拥有自己的独特的特性,这就是"继承" ...
- JAVA接口继承、抽象类等
1.定义接口 package test.intefaces; public interface TestIntefaceA { void testA(); void testB(); void tes ...
- Java面向对象㈡ -- 继承与多态
Java的继承是通过extends和implement来实现的,Java不支持多继承,但是Java支持多层继承以及多实现(接口).Java继承有一个关键字super是用来指向父类.Java继承衍生出覆 ...
- Java基础10 接口的继承与抽象类
链接地址:http://www.cnblogs.com/vamei/archive/2013/03/31/2982240.html 作者:Vamei 出处:http://www.cnblogs.com ...
- java基础-继承
浏览以下内容前,请点击并阅读 声明 一个由其他类继承的类叫子类(也叫继承类,扩展类等),该类继承的类叫父类或超类.除了Object类意外,所有的类都有切仅有一个父类,如果一个类没有用extends关键 ...
随机推荐
- Mybatis(基于SqlSessionTemplate的实现) + Spring 练习实战
mybatis学习篇:上次使用映射接口实现Mybatis,有不方便指出就是需要接口,且需要保证接口上不能存在其他的代理.这次通过SqlSessionTemplate基于模板类实现Mybatis,总的来 ...
- 比最差的API(ETW)更差的API(LTTng)是如何炼成的, 谈如何写一个好的接口
最近这几天在帮柠檬看她的APM系统要如何收集.Net运行时的各种事件, 这些事件包括线程开始, JIT执行, GC触发等等. .Net在windows上(NetFramework, CoreCLR)通 ...
- 51、css初识
前端内容就分三部分html.css.javascript(js),对一个网页来说html相当于是一个裸体的人,css相当于给这个人穿上了衣服,javascript相当于给这个人赋予动作行为,今天我们要 ...
- 创建一个可用的简单的SpringMVC项目,图文并茂
转载麻烦注明下来源:http://www.cnblogs.com/silentdoer/articles/7134332.html,谢谢. 最近在自学SpringMVC,百度了很多资料都是比较老的,而 ...
- Winccflexable触摸屏的报警
1.报警的分类 2.自定义报警分类 3.报警组成 4.Winccflexable中预定义的报警类别 5.报警的确认 6.WinccFlexable报警的显示 1)报警视图 2)报警窗口 3).报警指示 ...
- bzoj 2752: [HAOI2012]高速公路(road)
Description Y901高速公路是一条重要的交通纽带,政府部门建设初期的投入以及使用期间的养护费用都不低,因此政府在这条高速公路上设立了许多收费站.Y901高速公路是一条由N-1段路以及N个收 ...
- express整合webpack的打包文件dist
对于我来说,第一次接触前后端整合问题的小白,刚开始是一脸懵逼,这个问题整整坑了我一个晚上加一个早上,现在写出来总结: 前端开发:vue-cli+webpack: 后台开发:nodejs框架expres ...
- rsync服务器的搭建
Rsync(remote synchronize)是一个远程数据同步工具,简要的概括就是主机于主机之间的文件目录数据的一个同步.下面就是rsync服务器的搭建过程. 系统环境 平台:Centos ...
- 基于编辑距离来判断词语相似度方法(scala版)
词语相似性比较,最容易想到的就是编辑距离,也叫做Levenshtein Distance算法.在Python中是有现成的模块可以帮助做这个的,不过代码也很简单,我这边就用scala实现了一版. 编辑距 ...
- css实现多行文本溢出显示省略号(…)全攻略
省略号在ie中可以使用text-overflow:ellipsis了,但有很多的浏览器都需要固定宽度了,同时ff这些浏览器并不支持text-overflow:ellipsis设置了,下文来给各位整理一 ...