Java笔记:抽象类、接口
这篇笔记主要是抽象类和接口,还有简单介绍下三种设计模式:模板模式、工厂模式、命令模式
1.抽象方法和抽象类
(1)抽象方法和抽象类都必须使用abstract修饰符来定义,包含抽象方法的类只能被定义成抽象类,抽象类里面可以没有抽象方法。抽象方法里面没有方法体。
(2)抽象类不能被实例化,不能使用new关键字来调用抽象类的构造器来创建抽象类的实例,只能被当成父类来继承。
package cn.lsl; public abstract class Shape {
{
System.out.println("抽象类的中的普通初始化块");
}
private String color;
public abstract double calPerimeter();
public abstract String getType();
public Shape(){}
public Shape(String color){
System.out.println("Shape的构造器");
this.color = color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
package cn.lsl; public class Triangle extends Shape {
private double a;
private double b;
private double c; public Triangle(String color, double a, double b, double c) {
super(color);
this.setSides(a, b, c);
} public void setSides(double a, double b, double c){
if(a>=b+c || b>=a+c || c>=a+b){
System.out.println("三角形两边之和必须大于第三边");
return;
}
this.a = a;
this.b = b;
this.c = c;
} @Override
public double calPerimeter() {
return a + b + c;
} @Override
public String getType() {
// TODO Auto-generated method stub
return "三角形";
}
}
package cn.lsl; public class Circle extends Shape{
private double radius;
public Circle(String color, double radius){
super(color);
this.radius = radius;
}
public void setRadius(double radius) {
this.radius = radius;
} @Override
public double calPerimeter() {
return 2 * Math.PI * radius;
} @Override
public String getType() {
return getColor() + "圆形";
} public static void main(String[] args) {
Shape s1 = new Triangle("黑色",3,4,5);
Shape s2 = new Circle("黄色",3);
System.out.println(s1.getType());
System.out.println(s1.calPerimeter());
System.out.println(s2.getType());
System.out.println(s2.calPerimeter());
}
}
2.接口
(1)接口是一种特殊的“抽象类”,接口里面不能包含普通方法,接口里面的方法都是抽象方法。
(2)接口定义的是一种规范,实现这个接口的类所要遵守的规范,接口不关心这些类内部的状态数据,也不关心这些类里方法的实现细节,它只是规定这批类里面必须提供哪些方法。
(3)定义接口使用的是interface关键字,接口可以有多个直接父接口,但接口只能继继承接口,不能继承类。
[修饰符] interface 接口名 extends 父接口1, 父接口2{ }
(4)接口里面不能包含构造器和初始化块,接口里面可以包含Field(只能是常量)、方法(只能是抽象方法)、内部类、枚举类
因为接口里面只能定义常量Field,所以以下两行代码的结果是一样的
int a = 15;
public static final int a = 15;
(5)因为接口里面定义的全部是抽象方法,所以接口里面不允许定义静态方法(不能使用static修饰接口里面定义的方法)
(6)当接口扩展父接口的时候,将会获得接口里面定义的所有抽象方法、常量、内部类、枚举类。
package cn.lsl;
interface interfaceA{
int a = 1;
void testA();
} interface interfaceB{
int b = 2;
void testB();
} interface interfaceC extends interfaceA, interfaceB{
int c = 3;
void testC();
} public class InterfaceTest {
public static void main(String[] args){
System.out.println(interfaceC.a);
System.out.println(interfaceC.b);
System.out.println(interfaceC.c);
}
}
因为interfaceC接口继承了interfaceA和interfaceB,所以interfaceC接口中获得他们的Field常量
可以通过接口名来访问常量Field
(7)一个类可以继承一个父类,并同时实现多个接口,实现接口用implements关键字。
一个类实现了一个或多个接口后,这个类必须完全实现这些接口里所定义的全部抽象方法,若这个类保留了从父类中继承到的抽象方法,那么这个类也必须定义成抽象类。
格式:
[修饰符] class 类名 extends 父类 implements 接口1, 接口2{ }
eg:一个模拟打印机的例子
package cn.lsl; public interface Output {
int MAX_CACHE_LINE = 50;
void out();
void getData(String msg);
}
package cn.lsl; public interface Product {
int getProduceTime();
}
package cn.lsl; public class Printer implements Output, Product {
private String[] printData = new String[MAX_CACHE_LINE];
private int dataNum = 0;
@Override
public int getProduceTime() {
// TODO Auto-generated method stub
return 45;
} @Override
public void out() {
// TODO Auto-generated method stub
while(dataNum > 0){
System.out.println("打印机打印:" + printData[0]);
//把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData, 1, printData, 0, --dataNum);
}
} @Override
public void getData(String msg) {
// TODO Auto-generated method stub
if(dataNum >= MAX_CACHE_LINE){
System.out.println("输出队列已满,添加失败");
}else{
printData[dataNum++] = msg;
}
} public static void main(String[] args) {
Output o = new Printer();
o.getData("Java");
o.getData("JavaSe");
o.out();
o.getData("Android");
o.getData("JavaEE");
o.out();
Product p = new Printer();
System.out.println(p.getProduceTime()); Object obj = p;
}
}
3.模板模式
如果一个抽象父类中提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,这就是一种模板设计模式。
例如以下一个例子,父类中的普通方法依赖于一个抽象方法,抽象方法则推迟到子类中提供实现。
package cn.lsl; public abstract class SpeedMeter {
private double turnRate;
public SpeedMeter(){}
public abstract double getRadius();
public void setTurnRate(double turnRate){
this.turnRate = turnRate;
}
public double getSpeed(){
return Math.PI * 2 * getRadius() * turnRate;
}
}
package cn.lsl; public class CarSpeedMeter extends SpeedMeter{
@Override
public double getRadius() {
return 0.28;
}
public static void main(String[] args) {
CarSpeedMeter csm = new CarSpeedMeter();
csm.setTurnRate(15);
System.out.println(csm.getSpeed());
}
}
4.工厂模式
接口体现的是一种规范和实现分离的思想,利用接口可以极好地降低程序各模块之间的偶尔,从而提高系统的可扩展性和可维护性。
一个情景案例:
假设有一个Conputer类要组合一个输出设备,有两种选择,一是让Computer类组合一个Printer,二是让Computer类组合一个Output。
假设让Computer类组合一个Printer对象,如果有一天要使用BetterPrinter来代替Printer,于是就要对Computer类源代码进行修改。如果系统中多个类组合了Printer,那么修改的工作量将非常大。
而如果采用Computer类组合一个Output类型的对象,将Computer类与Printer类完全分离。那么当Printer对象切换到BetterPrinter对象时,系统完全不受影响。
package cn.lsl; public class Computer {
private Output out;
public Computer(Output out){
this.out = out;
}
public void keyIn(String msg){
out.getData(msg);
}
public void print(){
out.out();
}
}
上面的程序Computer不再负责创建Output对象,而是提供一个Output工厂来负责生成Output对象。
package cn.lsl; public class OutputFactory {
public Output getOutput(){
//return new Printer();
return new BetterPrinter();
}
public static void main(String[] args) {
OutputFactory of = new OutputFactory();
Computer c = new Computer(of.getOutput());
c.keyIn("Java");
c.keyIn("JavaSe");
c.print();
}
}
上面程序由getOutput()这个方法返回一个Output实现类的实例,具体要创建哪个对象由该方法决定。如果要将Printer改成BetterPrinter实现类,只要让BetterPrinter实现Output接口,
并改变OutputFactory类中的getOutput方法即可。
package cn.lsl; public class BetterPrinter implements Output, Product {
private String[] printData = new String[MAX_CACHE_LINE];
private int dataNum = 0;
@Override
public int getProduceTime() {
// TODO Auto-generated method stub
return 45;
} @Override
public void out() {
// TODO Auto-generated method stub
while(dataNum > 0){
System.out.println("高速打印机打印:" + printData[0]);
//把作业队列整体前移一位,并将剩下的作业数减1
System.arraycopy(printData, 1, printData, 0, --dataNum);
}
} @Override
public void getData(String msg) {
// TODO Auto-generated method stub
if(dataNum >= MAX_CACHE_LINE){
System.out.println("输出队列已满,添加失败");
}else{
printData[dataNum++] = msg;
}
} public static void main(String[] args) {
Output o = new BetterPrinter();
o.getData("Java");
o.getData("JavaSe");
o.out();
o.getData("Android");
o.getData("JavaEE");
o.out();
Product p = new BetterPrinter();
System.out.println(p.getProduceTime()); Object obj = p;
}
}
并改变
public Output getOutput(){
return new BetterPrinter();
}
5.命令模式
有这样一个场景:某个方法要完成某一个行为的时候,但这个行为的具体实现无法确定,必须等到执行该方法时候才可以确定。这个方法不仅需要普通数据可以变化,甚至还有方法执行体也需要变化。
我们可以用命令模式来完成这个场景。
package cn.lsl; public interface Command {
void process(int[] target);
}
Command接口里面定义了一个process方法,这个方法没有方法体,因为无法确定这个处理行为
package cn.lsl; public class ProcessArray {
public void process(int[] target, Command cmd){
cmd.process(target);
}
}
ProcessArray类里面包含一个process方法,这个方法无法确定处理数组的行为,所以传入一个参数,这个Command参数负责对数组的处理行为。
通过Command接口,实现ProcessArray类与具体“处理行为”分离。
package cn.lsl; public class PrintCommand implements Command{ @Override
public void process(int[] target) {
// TODO Auto-generated method stub
for(int tmp : target){
System.out.println("迭代数组:" + tmp);
}
}
}
package cn.lsl; public class AddCommand implements Command{ @Override
public void process(int[] target) {
// TODO Auto-generated method stub
int sum = 0;
for(int tmp : target){
sum += tmp;
}
System.out.println("数组总和:" + sum);
}
}
package cn.lsl; public class CommandTest {
public static void main(String[] args) {
ProcessArray pa = new ProcessArray();
int[] target = {1,2,5,3};
pa.process(target, new PrintCommand());
System.out.println("---------------");
pa.process(target, new AddCommand());
}
}
Java笔记:抽象类、接口的更多相关文章
- Java学习笔记 抽象类 接口 多态
instanceof 对象名 instanceof 类名 该对象是否属于该类 Animal animal = new Dog(); if(animal instanceof Dog){ Dog d = ...
- 10-01 Java 类,抽象类,接口的综合小练习--运动员和教练
运动员和教练的案例分析 运动运和教练的案例 代码实现 /* 教练和运动员案例 乒乓球运动员和篮球运动员. 乒乓球教练和篮球教练. 为了出国交流,跟乒乓球相关的人员都需要学习英语. 请用所学知识: 分析 ...
- JAVA笔记7__接口应用/Object类/简单工厂模式/静态代理模式/适配器模式
/** * 接口应用 */ public class Main { public static void main(String[] args) { Person p = new Person(&qu ...
- java特殊抽象类-接口
- Effective java笔记(三),类与接口
类与接口是Java语言的核心,设计出更加有用.健壮和灵活的类与接口很重要. 13.使类和成员的可访问性最小化 设计良好的模块会隐藏起所有的实现细节,仅使用API与其他模块进行通信.这个概念称为信息隐藏 ...
- Java抽象类接口、内部类题库
一. 选择题 1. Person类和Test类的代码如下所示,则代码中的错误语句是( C ).(选择一项) public class Person { public String nam ...
- JAVA:抽象类VS接口
JAVA中抽象类和接口的区别比较,以及它们各自的用途. 1.JAVA抽象类: 抽象类除了不能实例化以外,跟普通类没有任何区别.在<JAVA编程思想>一书中,将抽象类定义为“包含抽象方法的类 ...
- 深入理解java的抽象类和接口(转载)
原文链接:http://www.cnblogs.com/dolphin0520/p/3811437.html 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的 ...
- 转:二十一、详细解析Java中抽象类和接口的区别
转:二十一.详细解析Java中抽象类和接口的区别 http://blog.csdn.net/liujun13579/article/details/7737670 在Java语言中, abstract ...
- 关于JAVA中抽象类和接口的区别辨析
今天主要整理一下新学习的有关于Java中抽象类和接口的相关知识和个人理解. 1 抽象类 用来描述事物的一般状态和行为,然后在其子类中去实现这些状态和行为.也就是说,抽象类中的方法,需要在子类中进行重写 ...
随机推荐
- .net 控件开发第二天 怎么将 第一天写的代码 用到 .net中来
前面第一天 我们看到的全是 js的代码,虽然不管是BS的框架是java 还是 php,复用性 还是特别高的, 但是 写起来比较费劲,怎么办,我们能不能 更 简单点呢? 当然可以,这个时候我们就要用到 ...
- crm创建和编辑全局选项集
一个选项集就是可包含在一个实体中的某种类型的字段.它定义一组选项.当一个选项集显示在窗口中时,将使用下拉列表控件.当在 Advanced Find 中显示时,则使用选择列表控件.有时,开发者将选项集称 ...
- curl_redir_exec()函数
function curl_redir_exec($ch,$debug="") { static $curl_loops = 0; static $curl_max_loops = ...
- Linux下查看使用频率最高的十个命令
这个shell是在linux吧一个小伙伴发的,链接已找不到,挺有意思的,隔段时间运行一次,可以看看自己最近都干了什么. [shell] history | awk '{CMD[$2]++;count+ ...
- Asterisk 未来之路3.0_0007
原文:Asterisk 未来之路3.0_0007 Modules Asterisk 是基于模块构建的.一个模块提供某个特定的功能,它是动态的被装载.比如:信道驱动(chan_sip.so),或可以连接 ...
- iOS文档序列化(对象归档)
对象归档: 概念: 对象归档是指将对象写入文件保存在硬盘,当再次又一次打开程序时,能够还原这些对象.也称:对象序列化.对象持久化. 数据持久性的方式(事实上就是3类) 1,NSKeyedArchive ...
- Java集合之HashMap源码实现分析
1.简介 通过上面的一篇随笔我们知道了HashSet的底层是采用Map实现的,那么Map是什么?它的底层又是如何实现的呢?这下我们来分析下源码,看看具体的结构与实现.Map 集合类用于存储元素对(称作 ...
- C#:判断当前程序是否通过管理员运行
原文:C#:判断当前程序是否通过管理员运行 public bool IsAdministrator() { WindowsIdentity current = WindowsIdentity.GetC ...
- SSIS中Sql Task 获取系统变量
原文:SSIS中Sql Task 获取系统变量 执行 SQL 任务使用不同的连接类型时,SQL 命令的语法使用不同的参数标记.例如,ADO.NET 连接管理器类型要求 SQL 命令使用格式为 @var ...
- des和Rijndael加密
------------IV的作用: 为了保证数据的安全,.NET基类库中提供的私钥算法类使用称作密码块链(CBC,Cipher Block Chaining)的链模式,算法使用一个密钥和一个初始化向 ...