一、抽象类的基本概念

普通类是一个完善的功能类,可以直接产生实例化对象,并且在普通类中可以包含有构造方法、普通方法、static方法、常量和变量等内容。而抽象类是指在普通类的结构里面增加抽象方法的组成部分。

那么什么叫抽象方法呢?在所有的普通方法上面都会有一个“{}”,这个表示方法体,有方法体的方法一定可以被对象直接使用。而抽象方法,是指没有方法体的方法,同时抽象方法还必须使用关键字abstract做修饰

拥有抽象方法的类就是抽象类,抽象类要使用abstract关键字声明。

范例:定义一个抽象类

abstract class A{//定义一个抽象类public void fun(){//普通方法System.out.println("存在方法体的方法");}public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰}

二、抽象类的使用

我们先看范例。
范例:直接实例化抽象类的对象

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public void fun(){//普通方法System.out.println("存在方法体的方法");}public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰}public class TestDemo {public static void main(String[] args) {A a = new A();}
}

运行:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: Cannot instantiate the type Aat com.wz.abstractdemo.TestDemo.main(TestDemo.java:15)

从上可知,A是抽象的,无法直接进行实例化操作。为什么不能直接实例化呢?当一个类实例化之后,就意味着这个对象可以调用类中的属性或者放过了,但在抽象类里存在抽象方法,而抽象方法没有方法体,没有方法体就无法进行调用。既然无法进行方法调用的话,又怎么去产生实例化对象呢。

抽象类的使用原则如下:
(1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public;
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理;
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类;
(4)子类(如果不是抽象类)则必须覆写抽象类之中的全部抽象方法(如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。);

范例:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public void fun(){//普通方法System.out.println("存在方法体的方法");}public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰}
//单继承
class B extends A{//B类是抽象类的子类,是一个普通类@Overridepublic void print() {//强制要求覆写System.out.println("Hello World !");}}
public class TestDemo {public static void main(String[] args) {A a = new B();//向上转型a.print();//被子类所覆写的过的方法}
}

运行结果:

Hello World !

现在就可以清楚的发现:
(1)抽象类继承子类里面有明确的方法覆写要求,而普通类可以有选择性的来决定是否需要覆写;
(2)抽象类实际上就比普通类多了一些抽象方法而已,其他组成部分和普通类完全一样;
(3)普通类对象可以直接实例化,但抽象类的对象必须经过向上转型之后才可以得到。

虽然一个类的子类可以去继承任意的一个普通类,可是从开发的实际要求来讲,普通类尽量不要去继承另外一个普通类,而是去继承抽象类。

三、抽象类的使用限制

(1)抽象类中有构造方法么?
由于抽象类里会存在一些属性,那么抽象类中一定存在构造方法,其存在目的是为了属性的初始化。
并且子类对象实例化的时候,依然满足先执行父类构造,再执行子类构造的顺序。

范例如下:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public A(){System.out.println("*****A类构造方法*****");}public abstract void print();//抽象方法,没有方法体,有abstract关键字做修饰}
//单继承
class B extends A{//B类是抽象类的子类,是一个普通类public B(){System.out.println("*****B类构造方法*****");}@Overridepublic void print() {//强制要求覆写System.out.println("Hello World !");}}
public class TestDemo {public static void main(String[] args) {A a = new B();//向上转型}}

执行结果:

*****A类构造方法*****
*****B类构造方法*****

(2)抽象类可以用final声明么?
不能,因为抽象类必须有子类,而final定义的类不能有子类;

(3)抽象类能否使用static声明?
先看一个关于外部抽象类的范例:

package com.wz.abstractdemo;static abstract class A{//定义一个抽象类public abstract void print();}class B extends A{public void print(){System.out.println("**********");}
}
public class TestDemo {public static void main(String[] args) {A a = new B();//向上转型a.print();}}

执行结果

Exception in thread "main" java.lang.Error: Unresolved compilation problem: Illegal modifier for the class A; only public, abstract & final are permittedat com.wz.abstractdemo.A.<init>(TestDemo.java:3)at com.wz.abstractdemo.B.<init>(TestDemo.java:9)at com.wz.abstractdemo.TestDemo.main(TestDemo.java:18)

再看一个关于内部抽象类:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类static abstract class B{//static定义的内部类属于外部类public abstract void print();}}class C extends A.B{public void print(){System.out.println("**********");}
}
public class TestDemo {public static void main(String[] args) {A.B ab = new C();//向上转型ab.print();}}

执行结果:

**********

由此可见,外部抽象类不允许使用static声明,而内部的抽象类运行使用static声明。使用static声明的内部抽象类相当于一个外部抽象类,继承的时候使用“外部类.内部类”的形式表示类名称。

(4)可以直接调用抽象类中用static声明的方法么?
任何时候,如果要执行类中的static方法的时候,都可以在没有对象的情况下直接调用,对于抽象类也一样。
范例如下:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public static void print(){System.out.println("Hello World !");}}public class TestDemo {public static void main(String[] args) {A.print();}}

运行结果:

Hello World !

(5)有时候由于抽象类中只需要一个特定的系统子类操作,所以可以忽略掉外部子类。这样的设计在系统类库中会比较常见,目的是对用户隐藏不需要知道的子类。
范例如下:

package com.wz.abstractdemo;abstract class A{//定义一个抽象类public abstract void print();private static class B extends A{//内部抽象类子类public void print(){//覆写抽象类的方法System.out.println("Hello World !");}}//这个方法不受实例化对象的控制public static A getInstance(){return new B();}}public class TestDemo {public static void main(String[] args) {//此时取得抽象类对象的时候完全不需要知道B类这个子类的存在A a = A.getInstance();a.print();}
}

运行结果:

Hello World !

四、抽象类的应用——模板设计模式

例如,现在有三类事物:
(1)机器人:充电,工作;
(2)人:吃饭,工作,睡觉;
(3)猪:进食,睡觉。
现要求实现一个程序,可以实现三种不同事物的行为。

先定义一个抽象行为类:

package com.wz.abstractdemo;public abstract class Action{public static final int EAT = 1 ;public static final int SLEEP = 3 ;public static final int WORK = 5 ;public abstract void eat();public abstract void sleep();public abstract void work();public void commond(int flags){switch(flags){case EAT:this.eat();break;case SLEEP:this.sleep();break;case WORK:this.work();break;case EAT + SLEEP:this.eat();this.sleep();break;case SLEEP + WORK:this.sleep();this.work();break;default:break;}}
}

定义一个机器人的类:

package com.wz.abstractdemo;public class Robot extends Action{@Overridepublic void eat() {System.out.println("机器人充电");}@Overridepublic void sleep() {}@Overridepublic void work() {System.out.println("机器人工作");}}

定义一个人的类:

package com.wz.abstractdemo;public class Human extends Action{@Overridepublic void eat() {System.out.println("人吃饭");}@Overridepublic void sleep() {System.out.println("人睡觉");}@Overridepublic void work() {System.out.println("人工作");}}

定义一个猪的类:

package com.wz.abstractdemo;public class Pig extends Action{@Overridepublic void eat() {System.out.println("猪进食");}@Overridepublic void sleep() {System.out.println("猪睡觉");}@Overridepublic void work() {}}

测试主类:

package com.wz.abstractdemo;public class AbstractDemo {public static void main(String[] args) {fun(new Robot());fun(new Human());fun(new Pig());}public static void fun(Action act){act.commond(Action.EAT);act.commond(Action.SLEEP);act.commond(Action.WORK);}}

运行结果:

机器人充电
机器人工作
人吃饭
人睡觉
人工作
猪进食
猪睡觉

所有的子类如果要想正常的完成操作,必须按照指定的方法进行覆写才可以,而这个时候抽象类所起的功能就是一个类定义模板的功能。

Java抽象类 详解相关推荐

  1. java 抽象类 详解

    目录 一.抽象类概述: 二.抽象方法 : 1.概述 : 2.应用 : 3.特点 : 三.抽象类特点 : 1.关于abstract关键字 : 2.抽象类不能被实例化,只能创建其子类对象 : 3.抽象类子 ...

  2. php面向对象代码_PHP面向对象之抽象类详解(代码实例)

    [摘要] PHP即"超文本预处理器",是一种通用开源脚本语言.PHP是在服务器端执行的脚本语言,与C语言类似,是常用的网站编程语言.PHP独特的语法混合了C.Java.Perl以及 ...

  3. 接口与继承系列教材 (十)- Java 内部类详解

    接口与继承系列教材 (十)- Java 内部类详解 内部类分为四种: 非静态内部类 静态内部类 匿名类 本地类 步骤1:非静态内部类 步骤2:静态内部类 步骤3:匿名类 步骤4:本地类 步骤5:在匿名 ...

  4. Java集合排序及java集合类详解

    Java集合排序及java集合类详解 (Collection, List, Set, Map) 摘要内容 集合是Java里面最常用的,也是最重要的一部分.能够用好集合和理解好集合对于做Java程序的开 ...

  5. Java接口 详解(二)

    上一篇Java接口 详解(一)讲到了接口的基本概念.接口的使用和接口的实际应用(标准定义).我们接着来讲. 一.接口的应用-工厂设计模式(Factory) 我们先看一个范例: package com. ...

  6. 常见的java设计模式详解

    常见的java设计模式详解 1. 根据目的来分 2 GoF的23种设计模式的功能 3.下面介绍几种常见的模式 单例(Singleton)模式 前言 1)单例(Singleton)模式的定义 2)特点 ...

  7. Apache Thrift - java开发详解

    2019独角兽企业重金招聘Python工程师标准>>> Apache Thrift - java开发详解 博客分类: java 架构 中间件 1.添加依赖 jar <depen ...

  8. Java泛型详解-史上讲解最详细的,没有之一

    目录 1. 概述 2. 一个栗子 3. 特性 4. 泛型的使用 4.1 泛型类 4.2 泛型接口 4.3 泛型通配符 4.4 泛型方法 4.4.1 泛型方法的基本用法 4.4.2 类中的泛型方法 4. ...

  9. Java虚拟机详解----JVM常见问题总结

    [正文] 声明:本文只是做一个总结,有关jvm的详细知识可以参考本人之前的系列文章,尤其是那篇:Java虚拟机详解04----GC算法和种类.那篇文章和本文是面试时的重点. 面试必问关键词:JVM垃圾 ...

  10. java 泛型详解、Java中的泛型方法、 java泛型详解

    本文参考java 泛型详解.Java中的泛型方法. java泛型详解 概述 泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用. 什么是泛型?为什么要使用泛型? 泛型,即& ...

最新文章

  1. Apache Kafka-生产者_批量发送消息的核心参数及功能实现
  2. 和 VMware、深信服、天翼云、招商云专家一起聊聊云原生边缘计算
  3. linux取消线程的原理,浅析 Linux 进程与线程
  4. 查询类网站或成站长淘宝客新金矿
  5. 给一个执行在windows 7和NAT下的VMWARE虚拟机分配固定IP
  6. 关于40G/100G高速PHY的测试
  7. [蛋蛋涂鸦]蜡笔蛋&某蛋真面目(表被吓着)
  8. 左对齐杨辉三角python_什么是左的错误?
  9. Windows如何清理C盘的缓存文件和删除恶意软件
  10. 基于FME实现地铁路径规划
  11. U3D[02.21]
  12. 银河麒麟安装docker-compose体验
  13. 用于单图像超分辨率的增强深度残差网络
  14. 软件系统的多维性能模型
  15. 【案例分析-初探】美国有多少家加油站?
  16. 类美团外卖、骑手、类快递取餐柜、整合菜品供应商、前厅、后厨、配送、智能厨电设备的智慧餐饮业务
  17. IDEA 如何控制编辑左侧的功能图标 ICON
  18. UltraEdit 15.10 注册码
  19. 太棒了,Python和算法简直是绝配
  20. 前端面试题总结以及vue在工作中常见的错误

热门文章

  1. Cloudera Manager集群报警,堆转储目录/tmp 或日志目录/var/log 可用空间小于 5.0 吉字节
  2. JavaScript基础若干盲点总结
  3. 关于广告投放系统:竞价策略(2018)
  4. 我的CSDN博客十年
  5. 用代码实现通过人人网的登录
  6. 如何优雅的给你的APK文件打上签名
  7. buck斩波电路matlab,直流斩波电路的MATLAB建模与仿真.doc
  8. 深度揭秘安全领域的那些“大牛” 竟过半在360
  9. 怎么将视频转换成mp4?
  10. 修改判断名字重复,保证名字唯一