JAVA之旅(七)——final关键字 , 抽象类abstract,模板方法模式,接口interface,implements,特点,扩展
JAVA之旅(七)——final关键字 , 抽象类abstract,模板方法模式,接口interface,implements,特点,扩展
OK,我们继续学习JAVA,美滋滋的
一.final
我们来聊聊final这个关键字
- final可以修饰类,方法和变量
- final修饰的类不可以被继承
- final修饰的方法不可以被覆盖
- final修饰的变量是一个常量,只能被赋值一次
- 内部类只能访问被final修饰的局部变量
final,故名思意,就是最终的意思,由以上的五种特性,不过final的出现,也是有弊端的,他破坏了封装性,对继承有了挑战,为了避免被继承,被子类复写功能,还有,当你描述事物时,一些数据的出现值是固定的,那么,这时为了增强阅读行,都给这个值起个名字方便阅读,而这值不需要改变,就会用到final去修饰,作为常量,常量的书写规范是所有字母都大写,如果由多个单词组成,单词间通过下划线链接!而且内部类定义在类中的局部位置只能访问该局部被final修饰的局部变量
final大家只要记住他的特性就行
二.抽象类
这个抽象类应该是属于继承的下半部分的,我们看一个标注的代码
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
    }
}
/**
 * 学生
 *
 * @author LGL
 *
 */
class student extends Base {
    void speak() {
        System.out.println("学习");
    }
}
/**
 * 工人
 *
 * @author LGL
 *
 */
class worker extends Base {
    void speak() {
        System.out.println("工作");
    }
}
/**
 * 基类
 *
 * @author LGL
 *
 */
class Base {
    void speak() {
        System.out.println("Hello");
    }
}
这里,学生和工人都是要说话,所以我们可以抽取,但是这里,他们说话的内容却是不同的,当多个类出现相同功能,但是功能主体不同,这个时候就可以进行向上抽取,这时只抽取功能主体;这个时候就得用到我们的抽象类了abstract;所以我们的基类是这样的
/**
 * 基类
 *
 * @author LGL
 *
 */
abstract class Base {
    abstract void speak();
}
什么叫抽象?
- 看不懂
特点
- 1.抽象方法一定定义在抽象类中
- 2.抽象方法和抽象类都必须被abstract关键字修饰
- 3.抽象类不可以用new创建对象,因为调用抽象方法没意义
- 4.抽象类中的方法要被使用必须由子类复写其所有的抽象方法后建立子类对象调用 
 - 如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类
 
其实抽象类和一般的类没有什么太大的不同,只是要注意该怎么描述事物就怎么描述事物,只不过该事物中出现了一些看不懂的东西,这些不确定的部分也是该事物的功能,需要明确出来,但是无法定义主体,通过抽象方法来表示!
- 抽象类比其他类多了抽象函数,就是在类中可以定义抽象方法
- 抽象类不可以实例化
特殊:抽象类中可以不顶用抽象方法,看上去很没有意义,但是这样做可以做到不让该类建立对象,不是很多见
抽象方法文字部分说了这, 多,我们做一个小练习
- 题目:假如我们在开发一个系统时需要对员工进行建模,员工包含三个属性 姓名,工号和工资,经理也是员工,除了含有员工的属性外,另外还 有一个奖金属性,请使用继承的思路设计出员工类和经理类,要求类 种提供必要的方法进行属性访问!
我们实现之前可以简单的分析一下,我们的员工类应该有三个属性,name,id,pay,而经历类,理论上是继承了员工类并且有资金的奖金属性,行,这样的话我们可以用代码去测试一下
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        /**
         * 假如我们在开发一个系统时需要对员工进行建模,员工包含三个属性 姓名,工号和工资,经理也是员工,除了含有员工的属性外,另外还
         * 有一个奖金属性,请使用继承的思路设计出员工类和经理类,要求类 种提供必要的方法进行属性访问!
         */
    }
}
/**
 * 员工类
 *
 * @author LGL
 *
 */
abstract class Employee {
    // 姓名
    private String name;
    // 工号
    private String id;
    // 工资
    private double pay;
    // 这个员工一生成,这三个属性必须有
    public Employee(String name, String id, double pay) {
        this.name = name;
        this.id = id;
        this.pay = pay;
    }
    // 员工做什么是不确定的
    public abstract void work();
}
/**
 * 经理类
 *
 * @author LGL
 *
 */
class Manager extends Employee {
    // 奖金
    private int bonus;
    public Manager(String name, String id, double pay, int bonus) {
        super(name, id, pay);
        this.bonus = bonus;
    }
    // 复写
    @Override
    public void work() {
        System.out.println("管理");
    }
}
这代码很清晰的就表现了抽象的关系
三.模板方法模式
这是一个小案例,获取一段程序的运行时间,这个需求应该很简单吧,计时,
- 原理:获取程序开始和结束的时间并相减
获取时间的方法:System.currentTimeMillis()
代码逻辑是这样写的
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        GetTime gt = new GetTime();
        gt.getTime();
    }
}
/**
 * 时间类
 *
 * @author LGL
 *
 */
class GetTime {
    // 获取时间
    public void getTime() {
        long start = System.currentTimeMillis();
        // 耗时
        for (int i = 0; i < 10000; i++) {
            System.out.print("" + i);
        }
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start));
    }
}我们就可以得到你代码运行的毫秒数了
但是我们发现,其实这个耗时的部分是不确定的,对吧,那既然这样,我们复写的话,就有点多余了,我们可以使用使用模板方法模式,也就是抽成一个方法公用
import org.ietf.jgss.Oid;
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        GetTime gt = new GetTime();
        gt.getTime();
    }
}
/**
 * 时间类
 *
 * @author LGL
 *
 */
class GetTime {
    // 获取时间
    public void getTime() {
        long start = System.currentTimeMillis();
        runCode();
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start));
    }
    /**
     * 耗时方法
     */
    private void runCode() {
        // 耗时
        for (int i = 0; i < 10000; i++) {
            System.out.print("" + i);
        }
    }
}这个时候,要是其他类想使用的话,就只要复写一个方法就行了,Test想使用的话,就可以直接继承复写了
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        // GetTime gt = new GetTime();
        Test t = new Test();
        t.getTime();
    }
}
/**
 * 时间类
 *
 * @author LGL
 *
 */
class GetTime {
    // 获取时间
    public void getTime() {
        long start = System.currentTimeMillis();
        runCode();
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start));
    }
    /**
     * 耗时方法
     */
    public void runCode() {
        // 耗时
        for (int i = 0; i < 10000; i++) {
            System.out.print("" + i);
        }
    }
}
class Test extends GetTime {
    @Override
    public void runCode() {
        // 耗时
        for (int i = 0; i < 50000; i++) {
            System.out.print("" + i);
        }
    }
}这样,输出的内容就是我们随便改的了
我们还可以用抽象去做,你就一定要去做这件事儿
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        // GetTime gt = new GetTime();
        Test t = new Test();
        t.getTime();
    }
}
/**
 * 时间类
 *
 * @author LGL
 *
 */
abstract class GetTime {
    // 获取时间
    public void getTime() {
        long start = System.currentTimeMillis();
        runCode();
        long end = System.currentTimeMillis();
        System.out.println("耗时:" + (end - start));
    }
    /**
     * 耗时方法
     */
    public abstract void runCode();
}
class Test extends GetTime {
    @Override
    public void runCode() {
        // 耗时
        for (int i = 0; i < 50000; i++) {
            System.out.print("" + i);
        }
    }
}我把这个延时的操作留给子类,你爱咋地就咋滴,这样是不是更方便?当然,我们可以给getTime加一个final修饰,这样就让程序更加的健壮;
当代码完成优化之后,就可以解决这类问题了,我们把这种方式叫做:模板方法设计模式
- 什么是模板方法?
在定义功能的时候,功能的一部分是不确定的,而确定的部分在使用不确定的部分的时候,那么这时就将不确定的 部分暴露出去让子类去完成,这就是吗,吗,模板方法模式了
四.接口
接口的关键字是interface,接口中的成员修饰符是固定的
- 成员常量:public static final
- 成员函数:public abstract
接口的出现将“多继承”通过另一种形势体现,即“多实现”
上面的都是概念。我还是通俗易懂的来说吧,接口,初期理解,你可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的形式表示,interface,class用于定义类,定义接口
接口定义时,格式特点在于
- 1.接口中常见的定义一个是常量,一个是抽象方法
- 2.接口中的成员都有固定修饰符
- 常量:public static final
- 方法:public abstract具体格式:
/**
 * 人的接口
 *
 * @author LGL
 *
 */
interface Person {
    public static final int AGE = 20;
    /**
     * 说话
     */
    public abstract void speak();
}
这里注意,接口中的成员都是public,我们要想使用这个接口,需要用到另一个关键字了implements
为什么我们类不能继承类呢?因为接口,是不可以创建对象的,因为有抽象方法,需要被子类去实现,子类对接口中的抽象方法全都覆盖过后子类才可以实例化,否则子类是一个抽象类
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        Student s = new Student();
        System.out.println(s.AGE);
        System.out.println(Student.AGE);
        System.out.println(Person.AGE);
    }
}
class Student implements Person {
    @Override
    public void speak() {
    }
}
/**
 * 人的接口
 *
 * @author LGL
 *
 */
interface Person {
    public static final int AGE = 20;
    /**
     * 说话
     */
    public abstract void speak();
}
这样执行的后,我们就等得到数据了
不过接口不仅仅是这么简单,接口是可以被类多实现了,什么叫做多实现?就是一个类单继承,但是可以实现多个接口,对继承不支持的形式,java支持多实现
class Student implements Person, Person2 {
    @Override
    public void speak() {
    }
    @Override
    public void work() {
    }
}
/**
 * 人的接口
 *
 * @author LGL
 *
 */
interface Person {
    public static final int AGE = 20;
    /**
     * 说话
     */
    public abstract void speak();
}
interface Person2 {
    public abstract void work();
}可以看到实现了;两个接口,但是他为什么没有继承的弊端呢?因为他没有方法主体,子类爱怎么着就怎么着了
接口间的关系时继承
接口的特点
这个接口的重点比较实在,所以单独提取出来讲一下,首先我们来连接一下接口的特点
- 接口谁对外暴露的规则
- 接口是程序的功能扩展
- 接口可以用力多实现
- 类和接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
- 接口与接口之间可以有继承关系
就好比笔记本,我们扩展一样,这就是接口的概念,说不如做,我们写个例子来展现:
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
    }
}
/**
 * 学生类
 *
 * @author LGL
 *
 */
abstract class Student {
    // 学习不确定
    abstract void study();
    // 都要睡觉
    void Sleep() {
        System.out.println("sleep");
    }
    //都抽烟
    abstract void smoke();
}
/**
 * 我
 * @author LGL
 *
 */
class lgl extends Student{
    @Override
    void study() {
        System.out.println("lgl学习");
    }
    @Override
    void smoke() {
        System.out.println("lgl 抽烟");
    }
}
我这里定义了一个人,他有抽烟,睡觉,学习的方法,学习的方法不确定,所以要抽象,睡觉都要,抽烟,有的人抽,有的不抽,品牌也不一样,所以也得弄成这样,现在我去继承这个人,机会有学习和睡觉的方法,但是强制性的抽烟了,这就是这个例子的问题,那我们要怎么改善?还得使用接口了,我们可以把抽烟的方法抽写成接口,有需要接实现这个接口
//公共的   类   类名
public class HelloJJAVA {
    // 公共的 静态 无返回值 main方法 数组
    public static void main(String[] str) {
        lgl l = new lgl();
        l.smoke();
        l.study();
    }
}
/**
 * 学生类
 *
 * @author LGL
 *
 */
abstract class Student {
    // 学习不确定
    abstract void study();
    // 都要睡觉
    void Sleep() {
        System.out.println("sleep");
    }
}
/**
 * 我
 *
 * @author LGL
 *
 */
class lgl extends Student implements smoke{
    @Override
    void study() {
        System.out.println("lgl学习");
    }
    @Override
    public void smoke() {
        System.out.println("lgl 抽烟");
    }
}
/**
 * 抽烟的接口
 * @author LGL
 *
 */
interface smoke {
    void smoke();
}
这样就可以输出
好的,我们本篇幅就先到这里,如果有不明白的地方,还是要多温习几遍哦,想学好android,java功底是必不可少的呢!
我创建一个很有意思的群:555974449,要是感兴趣的可以进来一起交流一下哦!
JAVA之旅(七)——final关键字 , 抽象类abstract,模板方法模式,接口interface,implements,特点,扩展的更多相关文章
- Java抽象类(Abstract Class)与接口(Interface)区别
		抽象类与接口比较 抽象类跟接口类似,都不能实例化,可能包含不需实现方法或已实现的方法. 抽象类可以定义一些不是静态或常量的字段,定义 public, protected, private访问级别的具体 ... 
- php中的抽象类(abstract class)和接口(interface)
		一. 抽象类abstract class 1 .抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类. 2 ... 
- -1-2 java 面向对象基本概念       封装继承多态 变量 this super  static 静态变量 匿名对象 值传递 初始化过程 代码块 final关键字 抽象类 接口 区别 多态  包 访问权限 内部类 匿名内部类 == 与 equal
		java是纯粹的面向对象的语言 也就是万事万物皆是对象 程序是对象的集合,他们通过发送消息来相互通信 每个对象都有自己的由其他的对象所构建的存储,也就是对象可以包含对象 每个对象都有它的类型 也就是 ... 
- Java  继承(extends)、抽象类(abstract)的特点用法原理(7)
		Java 中的继承 继承: java中的抽象类用法原理: /* 当多个类中出现相同功能,但是功能主体不同, 这是可以进行向上抽取.这时,只抽取功能定义,而不抽取功能主体. 抽象:看不懂. 抽象类的特 ... 
- JAVA的abstract修饰符 && 接口interface用法 && 抽象类和interface的差别
		abstract修饰符可以修饰类和方法. (1)abstract修饰类,会使这个类成为一个抽象类,这个类将不能生成对象实例,但可以做为对象变量声明的类型(见后面实例),也就是编译时类型.抽象类就相当于 ... 
- 2017.10.23  Java 面向对象深入学习---final 关键字、static关键字、匿名对象等
		今日内容介绍 1.final 关键字 2.static 关键字 3.匿名对象 4.内部类 5.包的声明与访问 6.访问修饰符 7.代码块 第一节课 01(面向对象)final关键字概念.avi 02: ... 
- 《JAVA学习笔记 (final关键字)》
		[14-9]面向对象-final关键字 /* 继承的弊端,打破封装性. 不让其他类继承该类,就不会有重写. 怎么能实现呢?通过Java中的一个关键子来实现,final(最终化). [final关键字] ... 
- Java的static和final关键字的用法
		static关键字的用法 static的意思是"'静态的",在java里面可用于修饰属性和方法. static关键字的应用应注意以下几种情形: 1.static作用于某个字段,一个 ... 
- 安卓开发(Java)中关于final关键字与线程安全性
		前言 学习新知识固然重要,但是时常往回看看,温故知新是很必要的.回顾一下线程安全性和final关键字. 正文 从Java 5开始,final keyword一个特殊用法是在并发库中一个非常重要且经常被 ... 
随机推荐
- python脚本批量生成数据
			在平时的工作中,经常会遇到造数据,特别是性能测试的时候更是需要大量的数据.如果一条条的插入数据库或者一条条的创建数据,效率未免有点低.如何快速的造大量的测试数据呢?在不熟悉存储过程的情况下,今天给大家 ... 
- MongoDB 查询文档
			语法 MongoDB 查询数据的语法格式如下: >db.COLLECTION_NAME.find() find() 方法以非结构化的方式来显示所有文档. 如果你需要以易读的方式来读取数据,可以使 ... 
- Bootstrap3 排版-缩略语
			当鼠标悬停在缩写和缩写词上时就会显示完整内容,Bootstrap 实现了对 HTML 的 <abbr> 元素的增强样式.缩略语元素带有 title 属性,外观表现为带有较浅的虚线框,鼠标移 ... 
- TreeMap倒序以及遍历
			TreeMap倒序 TreeMap默认是按照Key给排序的,但是有的时候我们需要倒序,比如Key是日期,我们需要按照日期倒序显示(最近的时间在前面),类似下面这种情况 TreeMap倒序方法 tree ... 
- Programming In Scala笔记-第四章、类和对象
			类似于Java,Scala中也有类和对象的概念. 一.类.属性和方法 1.类 类是对一类事物的抽象,当一个类被定义后,就可以以该定义为模板,定义该类的一系列对象.比如说有以下一个模板 人类: 有姓名: ... 
- cassandra 常见问题
			摘要 本文主要介绍在部署cassandra集群以及使用cassandra过程中遇到的一些问题. 文章只发布在CSDN 和个人站点 更多nosql文章可以访问stone fang 个人主页 正文 Q1: ... 
- [OpenCV] 编译源程序 2.4.10 以支持 CUDA
			对源代码进行如下修改: H:\Software\opencv\sources\modules\gpu\src\nvidia\core\NCV.cu中添加 #include <algorithm& ... 
- Android通知Notification全面剖析
			通知 通知是您可以在应用的常规 UI 外部向用户显示的消息.当您告知系统发出通知时,它将先以图标的形式显示在通知区域中.用户可以打开抽屉式通知栏查看通知的详细信息. 通知区域和抽屉式通知栏均是由系统控 ... 
- PHP Ajax JavaScript 实现 无刷新附件上传
			普通表单 前端页面 后台处理 带有文件的表单 刷新方式 前端界面 后台页面 无刷新方式 大文件上传 POST极值 upload极值 上传细节 前端页面 后台处理 总结 对一个网站而言,有一个基本的不可 ... 
- Ruby 连接MySQL数据库
			使用Ruby连接数据库的过程还真的是坎坷,于是写点文字记录一下. 简介 Ruby简介 RubyGems简介 包管理之道 比较著名的包管理举例 细说gem 常用的命令 准备 驱动下载 dbi mysql ... 
