今天继续回顾Java基础,有些东西用得不多,大家看看知道语法就好

主要内容

抽象类

抽象方法

抽象方法的写法

抽象方法是否可以私有化

抽象类的特征

抽象类有无构造器,能否实例化对象

抽象类的结构

抽象类的核心意义

被继承

部分实现,部分抽象

接口

为什么要使用接口

接口和实现类的格式

接口的结构

JDK1.8之前

JDK1.8之后新增

接口VS父类

接口VS抽象类

代码块

静态代码块

构造代码块

普通代码块

构造器和代码块的执行顺序

final 关键字

修饰类

修饰方法

修饰变量

final和abstract的关系

单例模式(概念)

枚举

为什么要用枚举

枚举的写法

枚举是个普通的类

写在最后

抽象类

自我学习Java以来,我在实际开发中基本没用过抽象类。但框架和JDK中很喜欢使用抽象类。抽象类作为一个父类,被用来描述一类事物应该具有的基本特征和功能,子类在此基础上进行扩展。是对子类的一种约束。

举个例子吧,学校的老师、校长和学生都是学校的一员,必须具备工作的能力(学习可以看作学生的工作),但是三者具体怎么工作是有差异的,具体怎么工作是自己决定的。看完这篇文章就会有概念了

构造方法

就上面的例子,如果写成代码的话应该是这样的,SchoolMember类代表学校成员,是一个父类,Teacher、Student和Principle都继承SchoolMember类,他们都有work方法

public class SchoolMember {

public String schoolName = "GDPU";

public void work() {

System.out.println("作为学校的成员一定要工作")

}

}

class Teacher extends SchoolMember{

@Override

public void work() {

System.out.println("我是个普通教师,教好自己的科目就可以了")

}

}

class Student extends SchoolMember{

@Override

public void work() {

System.out.println("我是个学生,读好书对得住爸妈就ok了")

}

}

class Principal extends SchoolMember{

@Override

public void work() {

System.out.println("我是校长,要让学校有条有理")

}

}

大家应该注意到了,其实SchoolMember类中的work方法中的内容并没有什么作用,反而浪费了内存空间。还不如不写

public class SchoolMember {

public String schoolName = "GDPU";

public void work() {

}

}

有一天,小明被爸妈安排到这个学校,小明便成为了学校的一员,但他无心向学在学校混日子,没有工作(学习)的能力

class Principal extends SchoolMember{

public void play() {

System.out.println("我就不读怎么滴")

}

}

学校觉得小明老这样很影响学校风气,于是把小明赶出了学校,学校一片祥和。但过一段时间又有像小明一样的学生进了这个学校,学校受不了了,最后决定只让一心向学的学生入学,便在自己的work方法上加了abstract关键字,变成抽象方法,学生必须重写这个方法才能算是学校的一员,才能继承SchoolMember类

抽象方法的写法

抽象方法被abstract修饰,没有方法体,只有方法签名

`public abstract 返回类型 方法签名(参数列表);

抽象方法是否可以私有化

可以,但是作为抽象方法不被子类重写还不如写成普通方法

抽象类的特征

我们可以把抽象类的特征概括为有得有失,抽象类得到了抽象方法的能力,却失去创建对象的能力。这里要注意,虽然抽象类有对方法进行抽象的能力,但他可以选择使用或不使用这种能力,也就是说,抽象类不一定有抽象方法,但是有抽象方法的类一定是抽象类

抽象类有无构造器,能否实例化对象

具有构造器

抽象类诞生的意义就是要给子类继承的,子类初始化一定会调用父类构造器super(...),所以抽象类必须有构造器

不能实例化对象

就拿上面的例子,如果`SchoolMember类被实例化,调用抽象方法将没有意义

SchoolMember s = new SchoolMember();

s.work(); // 方法没有实现,没有意义

抽象类本来就意味着一类事物是抽象的(不具体的),没有必要将他实例化

抽象类的结构

抽象类除了可以有普通类都有可以有的成员变量、成员方法、代码块、内部类*和构造器以外,还可以有抽象方法

再次强调,可以有不代表一定有哈

抽象类的核心意义

抽象类有没有体现他存在的价值,主要是看两方面,一是有没有被子类继承,二是有没有做到部分实现部分抽象的效果

被继承

一个抽象类如果不被子类继承,还不如做回普通类,还能被实例化

部分实现,部分抽象

一个抽象类作为父类,它可以先为子类实现相同的部分公共代码,剩下的由子类自由发挥。这里运用了设计模式中的模板模式

设计模式:前辈在生产实践中发明的优秀软件架构或思想,后人可以直接使用这些优秀架构和思想生产优秀的代码,

模板模式:使用部分实现部分抽象的思想编写模板,相同的功能不需要重复写,提高代码的可扩性,系统的可维护性,这就类似于我们使用英语作文模板,作文比较容易拿高分,第一段和最后一段都模板已经写好了,中间的部分自己写就得了

abstract class EnglishModel{

public void wirteTitle() {

System.out.println("这是模板的标题");

}

public void wirteHead() {

System.out.println("这是模板的第一段");

}

public void wirteTail() {

System.out.println("这是模板的最后一段");

}

public abstract void wirteTitle();

}

class MyEnglishWord extends EnglishModel{

@Override

public void wirteTitle() {

System.out.println("用模板真的爽");

}

}

这样我们只要负责写MyEnglishWord类就可以完成这份连半个英文都没有的英语作文了

接口

说到接口,一个带我做项目的师兄跟我说,接口是业务代码的抽象。当时没懂,之后自己学框架搭项目写代码的时候慢慢就有感觉啦,我们写Service层的代码应该都是先创建一个接口再创建一个实现类实现这个接口的吧,为什么要这样做呢

为什么要使用接口

我的理解是这样的,通常一个项目是由很多人一起做,你负责一个模块我负责另一个模块,试想一下,如果没有接口,我开发的是用户基础信息模块,你开发的是订单管理模块,现在有一个场景,你创建订单后需要查一下这个用户是不是VIP,是的话给他免运费,那你的代码会有这样一句话

UserService userService = new UserService();

boolean isVIP = userService.isVIP(userId);

但是我可能还没有写这个isVIP方法,可能我判断是不是VIP的方法不叫这个名字,甚至我连这个UserService类都还没创建呢,那你的代码一定是被编译器标红,这就很难受了,你得跑过来问我判断VIP的方法叫什么名字,要传入什么参数,出来什么结果,什么时候才开始写这个方法

如果我先创建接口可以解决上面的问题

你不用问我判断VIP的方法叫什么,你看我的接口文件就可以了

你的代码不会被标红,因为判断`VIP的方法存在,只是还没实现

你不用管我是怎么实现这个方法的,你调用就行了

所以总结一下:

接口是一种代码规范,你我都遵守才能同时一起做开发

接口也是业务代码的抽象,调用者不需要知道这个方法内部的实现过程

同时Java的接口可以弥补类的单继承的短板

接口和实现类的格式

接口

public interface 接口名 extends 接口1, 接口2...

实现类

修饰符 class 实现类的名称 implements 接口1, 接口2...

接口的结构

jdk1.8以后对接口的结构进行了修改,这里分开讲

JDK1.8以前

接口只有全局常量和抽象方法l两部分

全局变量

public static final 类型 常量名 = 常量;

常量名一般用英文大写加下划线的形式,public static可以省略不写

抽象方法

`public abstract 返回类型 方法签名(参数列表);

这里的`public abstract可以省略不写

JDK1.8以后新增

默认方法 (相当于实例成员方法,接口实现类可以直接调用)

class Main implements A{

public static void main(String[] args) {

Main m = new Main();

m.test();

}

}

interface A {

public default void test() {

// 默认方法

}

}

其中public default中的public可以省略。还有一种情况,如果Main类实现了两个接口,两个接口都有一样名字的方法怎么办?

class Main implements A{

public static void main(String[] args) {

Main m = new Main();

m.test();

}

@Override

public void test() {

// 真正执行的方法

System.out.println("重写方法");

}

}

interface A {

public default void test() {

// 默认方法A

System.out.println("默认方法A");

}

}

interface B {

public default void test() {

// 默认方法B

System.out.println("默认方法B");

}

}

重写方法

静态方法 (必须用接口名调用)

public static void test(){

// 静态方法

system.out.println("静态方法");

}

Test.test();

私有方法 (只有内部可以调用)

private void run() {

// 私有方法

system.out.println("私有方法");

}

这是JDK1.9后才有的部分

接口VS父类

继承父类的叫子类,父类只有一个父类,可以有多个子类

实现接口的叫实现类,接口可以有多个父接口,多个实现类

如果父类和接口同时存在一样的方法,优先执行父类中的方法

接口VS抽象类

相同点:接口和抽象类都不能被实例化,都可以包含抽象方法

不同点:抽象类具有普通类的结构,但他只能单继承一个父类,接口的组成成分比抽象类少,但可以继承多个父接口

代码块

代码块也是类的五个组成成分之一,分为静态代码块、构造代码块和普通代码块

静态代码块

静态代码块属于类,语法如下,主要作用是初始化静态资源,如静态成员变量、数据库连接等

public static String schoolName

static{

// 静态代码块

schoolName = "GDPU";

}

构造代码块

构造代码块属于对象,对象被创建的时候内部代码会被执行,用于初始化对象的资源

private String studentName;

{

// 动态代码块

this.studentName = "Rhythm";

}

普通代码块

在成员方法里我们可以用大括号把一段代码包起来,在里面声明的局部变量在外面不能使用

public void test() {

{

int i = 0;

}

System.out.println(i); // 报错

}

构造器和代码块的执行顺序

如果是个普通类

静态代码块

构造代码块

构造器

普通代码块

如果是个子类,这个非常重要,大家要理解并记住

父类静态代码块(先加载父类.class文件)

子类静态代码块(再加载子类.class文件)

父类构造代码块(父类对象被创建前执行)

父类构造器(子类构造器执行super())

子类构造代码块(子类对象被创建前执行)

子类构造器(创建子类对象)

final 关键字

这个大家平时应该用过吧,它可以在类、变量和方法上出现

修饰类

该类不能被继承,断子绝孙。String类就是用final修饰的

修饰方法

修饰静态成员方法 (没有什么效果)

修饰实例成员方法 (方法不能被子类重写)

变量

Java中变量分为局部变量和成员变量

成员变量

静态成员变量:这个其实就是我们平时定义常量的方式

public static final String USER_NAME = "Rhythm"

实例成员变量:只允许一次复赋值

private final int i = 10;

局部变量

final修饰局部变量是为了保护数据,防止程序员不小心把值给改了。比如下面这段代码,parse方法计算折后价,rate表示折扣,我们不希望rate在计算中被修改,可以加上final关键字

public class Test {

public static void main(String[] args) {

System.out.println(parse(10, 0.8));

System.out.println(parse(100, 0.7));

}

public double parse(double rmb, final double rate) {

return rmb * rate;

}

}

final和abstract的关系

互斥关系,final修饰的类不能被继承,但抽象类不被继承没有意义,final修饰方法不能被重写,抽象方法也没有意义

单例模式 (概念)

单例模式保证对象在运行过程中只被实例化一次,具体实现方式有很多种,这里只是对单例模式的简单引出,没有考虑并发情况

饿式

就是在类中的资源被使用时初始化对象

public class Main {

public static void main(String[] args) {

Demo demo = Demo.getDemo();

}

}

class Demo {

public static Demo demo;

static {

demo = new Demo();

System.out.println("对象被初始化");

}

private Demo() {

// 构造器私有

}

public static Demo getDemo() {

return demo;

}

public static void other() {

System.out.println("这是个其他方法");

}

}

缺点就是如果类中有其他静态成员方法如other被调用的时候对象也会被初始化

懒式

就是真的需要的时候才加载,大家看代码就懂了

class Demo {

public static Demo demo;

private Demo() {

// 构造器私有

}

public static Demo getDemo() {

if (demo == null) {

demo = new Demo();

}

return demo;

}

public static void other() {

System.out.println("这是个其他方法");

}

}

调用类中的其他方法不会初始化对象

注意:

构造器必须私有化

这里只是简单介绍下概念,以后再来总结详细的单例模式

枚举

枚举在实际开发中常常使用到,这里对他进行了总结

为什么要使用枚举

大家在代码中常常会使用常量来代替一些数字,提高代码可读性,对比一下下面两段代码,显然第二种可读性更高

public static void control(Integer i) {

if (i = 1) {

// 打开

} else {

// 关闭

}

}

public static void main(String[] args) {

control(1)

}

public static final Integer OPEN = 1;

public static final Integer CLOSE = 2;

public static void control(Integer i) {

if (i = OPEN) {

// 打开

} else {

// 关闭

}

}

public static void main(String[] args) {

control(OPEN)

}

但是对于我们来说,我们还是可以通过control(1)来调用方法的,为了保证代码的可读性,我们可以对这些常量进行约束管理,把常量抽出来放到一个类中

class Counst {

public static final Integer OPEN = 1;

public static final Integer CLOSE = 2;

}

以后使用就要这样写

if(i = Counst.OPEN) {

// 打开

}

于是Java将这些专门存放常量的类称为枚举类,并赋予他特殊的语法

枚举的写法

举个例子,我们运行完业务代码之后需要将数据返回到前端时要带上状态码code和提示信息message,这些值都是固定的,我们可以把它们抽出来做成枚举

public enum ResultCodeEnum {

SUCCESS(200, "操作成功"),

FAILED(500, "操作失败");

private long code;

private String message;

ResultCodeEnum(long code, String message) {

this.code = code;

this.message = message;

}

public long getCode() {

return code;

}

public String getMessage() {

return message;

}

}

总结起来就是:

enum定义类

定义常量对应的变量,可以定义多个,如上面的Integer code和String message

定义常量,如上面的SUCCESS(200, "操作成功"),用逗号隔开

提供get和set方法

定义一些自定义方法,如

public static String getMessageCode(Integer code) {

for (ResultCodeEnum item : ResultCodeEnum.values()) {

if (item.getCode() == code) {

return item.message;

}

}

return null;

}

枚举类是个普通的类

我们可以用javap查看一下枚举类的字节码

public final class ResultCodeEnum extends java.lang.Enum {

public static final ResultCodeEnum SUCCESS;

public static final ResultCodeEnum FAILED;

public static ResultCodeEnum[] values();

public static ResultCodeEnum valueOf(java.lang.String);

public long getCode();

public java.lang.String getMessage();

public static java.lang.String getMessageCode(java.lang.Integer);

static {};

枚举类继承了lang.Enum,并初始化了SUCCESS和FAILED两个ResultCodeEnum对象,提供了几个方法,所以我们在使用过程中把枚举类看成普通类就可以了

写在最后

这篇文章主要讲述了抽象类、接口、代码块、final关键字、单例模式和枚举,有些我们平时用不上的记住语法就好,面试的时候还能说一说,如果我的理解有误的话欢迎大家评论告诉我

java final类的写法_重拾JavaSE基础——抽象类、接口、代码块、final和枚举相关推荐

  1. java 多态判断非空_重拾JavaSE基础——多态及其实现方式

    今天是比较抽象的多态,希望能给大家带来帮助 主要内容 多态 为什么使用多态 多态的形式 多态的概念 多态的劣势 多态存在的必然条件 类型转换 多态的实现原理 多态的分类 运行时多态的形式 实现原理 常 ...

  2. 重拾JavaSE学习笔记

    重拾JavaSE学习笔记 1.常用DOS命令 2.了解Java 2.1 .java特性 2.2.JDK .JRE.JVM 2.3.java的加载和执行 3.开发环境搭建 3.1.安装jdk 3.2.配 ...

  3. 零基础入门 自学 JAVA SE 基础篇(九)instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface)

    JAVA SE自学 基础篇 多态 instanceof final 开闭原则 多态 抽象(abstract)方法与抽象类 接口(interface) 目标 父类型与子类型之间的转换及instanceo ...

  4. Java笔记017-类变量和类方法、理解main方法语法、代码块、单例设计模式、final关键字

    目录 面向对象编程(高级部分) 类变量和类方法 类变量-提出问题 传统方法解决 问题分析: 类变量快速入门 类变量内存布局 什么是类变量 如何定义类变量定义语法: 如何访问类变量 定义语法: 类变量使 ...

  5. java实验 类和对象_java 实验(三) 类和对象

    一.实验目的和要求 1. 掌握类的构造函数的重载 2. 深入理解类和对象 3. 学习NetBeans中UML项目的创建类并生成相应代码的方法 二.实验内容和原理 设计一个复数类,能够完成复数之间的基本 ...

  6. java工具类怎么写_常用的Java工具类——十六种

    常用的Java工具类--十六种 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选 ...

  7. -1-2 java 面向对象基本概念 封装继承多态 变量 this super static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口

    java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型  也就是 ...

  8. Java基础-day08-static·static静态代码块·final 关键字·多态·汽车设计综合案例·异常

    day09 1.static 是java中的一个关键字 用于修饰成员(成员变量和成员) 1.static是一个关键字 2.static可以修饰成员变量和方法,被修饰的资源就是静态资源 3.静态资源优先 ...

  9. java主类与源代码名称_Java高级编程基础:类文件结构解析,看穿Class代码背后的秘密...

    类文件结构 在说完了JVM内部结构后,接下来我们需要说一下另外一个非常重要的基础概念Class类结构. 我们既然知道了开发的Java源代码会首先被编译成字节码文件保存,JVM的类加载器会读取这些文件内 ...

最新文章

  1. 分组[测试点分支+二分图判定]
  2. 递归函数实现二分查找法
  3. Java数据解析之XML(原创)
  4. 手机modem开发(5)---LTE基本架构
  5. 8-Spring Boot消息服务
  6. 为你的.NET/Mono应用程序加入更新支持NetSparkle
  7. spring @POSTConstruction注解的作用
  8. 科研院所推进6S管理的难点及推进手段分析
  9. codesys 轴程序
  10. Safari Web Extension 开发(1)
  11. 云服务器复现PointRCNN代码踩坑总结
  12. qq不能发说说显示服务器错误,qq为什么发送不成word服务器拒绝发送离线请求. - 卡饭网...
  13. 树莓派 --- 人脸口罩识别智能监控
  14. 南京航空航天大学计算机考研经验贴
  15. FF新推荐新闻删除方法
  16. Dev-C++的使用(一):下载、安装与基本使用
  17. python程序设计是什么专业-那门用Python讲授的程序设计课程能带给学生什么?
  18. x86 版的 Arduino Intel Galileo 开发板的体验、分析和应用
  19. deepin20安装calibre4.17.0(kindle最佳伴侣)
  20. 银联前置的一些基本知识

热门文章

  1. Python 把函数视作对象
  2. fprintf与fwrite的区别
  3. 解决GitHub报错:schannel:failed to receive handshake, SSL/TLS connection failed
  4. 3.1.10 OS之基本分段存储管理(段表、地址变换、信息共享)
  5. python菜鸟教程shell_[python小白]菜鸟教程---
  6. Qt / Qt5 事件(event)机制详解
  7. MySQL / 自带的四个数据库介绍
  8. java多线程优先级的方法_Java多线程以及线程优先级
  9. 四位先行进位电路逻辑表达式_数字电子技术考试卷以及答案(4套)
  10. android 自定义dialog iphone,Android用DialogFragment实现iphone样式的圆角对话框 – 思,无邪...