Java编程思想之九 接口
接口和内部为我们提供了一种将接口与实现分离的更加结构化的方法。
抽象类和抽象方法
创建一个抽象类是希望通过这个通用接口操纵一系列类。
Java提供了一个叫做抽象方法的机制,这种方法是不完整的;仅声明而没有方法体。
abstract void f();
包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,那么该类必须限定为抽象的。
如果从一个抽象类继承,并想创建该新类的对象,那么就必须为基类的所有抽象方法提供方法定义。
9.2 接口
一个接口表示:所有实现该特定接口的类看起来都像这样。任何使用某特定接口的代码都指定可以调用该接口的哪些方法,而且仅需要知道这些。接口被用来建立类与类之间的协议。
interface不仅仅是一个极度抽象的类,它允许人们通过创建一个能够被向上转型的多种基类的类型,来实现某种类似多重继变种的特性。
创建一个接口,需要用到interface替换关键字class。
9.3 完全解耦
只要一个方法操作的是类而非接口,那么你就只能使用这个类及其子类。
创建一个能够根据所传递参数对象不同而具有不同行为的方法,这被称为策略模式。这类方法包含所有执行的算法中固定不变的部分,而策略包含变化的部分。策略就是传递进去的参数对象,它包含要执行的代码。
class Process{
public String name(){
return getClass().getName();
}
Object process(Object input){
return input;
}
}
class Process1 extends Process{
Object process(Object input){
return ((String)input).toUpperCase();
}
}
class Process2 extends Process{
Object process(Object input){
return ((String)input).toLowerCase();
}
}
class Process3 extends Process{
Object process(Object input){
return ((String)input).toCharArray()[0];
}
}
class Process4 extends Process{
Object process(Object input){
return ((String)input).toCharArray()[1];
}
}
public class Apply {
public static void processint(Process p,Object s){
System.out.println("Process:"+p.name()+"+"+p.process(s));
}
public static void main(String[] args){
processint(new Process1(),"S1");
processint(new Process2(),"s2");
processint(new Process3(),"s3");
processint(new Process4(),"s4");
}
}
9.4 Java中的多重继承
接口不仅仅只是一种更纯粹形式的抽象。因为接口是根本没有任何具体实现的:没有任何与接口相关的存储,所有,多个接口可以组合。
在导出类中,不强制必须有一个是抽象的或具体的基类,如果从一个非接口类继承,就只能是一个,其余元素都必须是接口。
interface CanFight{
void fight();
}
interface CanFly{
void fly();
}
interface CanSwim{
void swim();
}
class Actions{
public void fight(){
}
}
class hero extends Actions implements CanFight,CanFly,CanSwim
{
//如果需要继承接口,则需要是public
@Override
public void fly() {
}
@Override
public void swim() {
}
}
当一个导出类中有基类和接口时,基类必须放在最前面。
使用接口的主要原因:能够向上转型为多个基类型。
第二个原因与使用抽象类相同:防止客户端程序员创建该类对象,并确保者仅仅是一个接口。
9.5 通过继承来扩展接口
public class HorrorShow {
static void u(Monster b){
b.manse();
}
static void v(DangerousMonster d){
d.manse();
d.destroy();
}
static void w(Lethal l){
l.kill();
}
public static void main(String[] args){
DangerousMonster barney =new DragonZilla();
u(barney);
v(barney);
Vampire vlad=new VeryBadVampire();
u(vlad);
v(vlad);
w(vlad);
}
}
interface Monster{
void manse();
}
interface DangerousMonster extends Monster{
void destroy();
}
interface Lethal{
void kill();
}
class DragonZilla implements DangerousMonster{
@Override
public void manse() {
}
@Override
public void destroy() {
}
}
interface Vampire extends DangerousMonster,Lethal{
void drinkBlood();
}
class VeryBadVampire implements Vampire{
@Override
public void manse() {
}
@Override
public void destroy() {
}
@Override
public void kill() {
}
@Override
public void drinkBlood() {
}
}
只可以将extends用于单一类,但是可以引用多个基类接口。但需要用逗号隔开。
9.5.1 组合接口时名字冲突
interface I1{
void f();
}
interface I2{
int f(int i);
}
interface I3{
int f();
}
class C0{
public int f(){
System.out.println("C0.f");
return 0;
}
}
class C1 implements I1,I2{
@Override
public void f() {
System.out.println("C1.f()");
}
@Override
public int f(int i) {
System.out.println("C1.f(i)");
return 0;
}
}
class C2 extends C1 implements I2{
@Override
public int f(int i) {
System.out.println("C2.f(i)");
return 0;
}
}
class C3 extends C0 implements I3{
public int f(int i){
System.out.println("C3.f(i)");
return 0;
}
}
/*class C4 extends C0 implements I1{
}*///无法使用
9.6 适配接口
允许同一个接口具有多个不同的实现。它的形式通常是:一个接受接口类型的方法,而该接口的实现和向该方法传递的对象则取决于方法的使用者。
接口的一种常见用法就是策略模式。
使用接口,你主要声明:你可以用任何你想要的对象来调用我的方法,只要你的对象遵循了我的接口。
我们可以再任何有类之上添加新的接口,所有这意味着让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式。这就是使用接口而不是类的强大之处。
9.7 接口中的域
接口中任何域都自动是static和final的。
public class C11 {
public static void main(String[] args){
System.out.println(A1.i1+":"+A1.i2+":"+A1.i3);
}
}
interface A1{
int i1=1,i2=2,i3=3;
}
9.7.1 初始化接口中的域
再接口中定义的域不能是空final,但是可以被非常量表达式初始化。
public class C11 {
public static void main(String[] args){
System.out.println(A1.i);
System.out.println(A1.i);
System.out.println(A1.i);
}
}
interface A1{
int i=new Random(47).nextInt(58);
}
既然域是static的,它们就可以再类第一次被加载时初始化,这发生在任何域首次被访问。
但这些域不是接口的一部分,它们的值被存储在该接口的静态存储区域类。
9.8 嵌套接口
接口可以嵌套在类或其他接口中。
public class NestingInterfaces {
public static void main(String[] args){
A a=new A();
A.D ad=a.getD();
}
public class BImp implements A.B {
@Override
public void f() {
}
class CImp implements A.C{
@Override
public void f() {
}
}
class EImp implements E{
@Override
public void g() {
}
}
class EGImp implements E.G{
@Override
public void f() {
}
}
class EImp2 implements E{
@Override
public void g() {
}
}
class EG implements E.G{
@Override
public void f() {
}
}
}
}
class A{
interface B{
void f();
}
public class BImp implements B{
@Override
public void f() {
}
}
private class BImp2 implements B{
public void f(){
}
}
public interface C{
void f();
}
class CImp implements C{
@Override
public void f() {
}
}
private class CImp2 implements C{
@Override
public void f() {
}
}
public interface D{
void f();
}
class DImp implements D{
@Override
public void f() {
}
}
private class DImp2 implements D{
@Override
public void f() {
}
}
public D getD(){
return new DImp2();
}
private D dRef;
public void receiveD(D d){
dRef=d;
dRef.f();
}
}
interface E{
interface G{
void f();
}
public interface H{
void f();
}
void g();
}
在类中嵌套接口就像非嵌套接口一样,可以拥有public和包访问两种可视性。
9.9 接口与工厂
接口是实现多继承的途径,而生成遵循某个接口的对象的典型方式就是工厂模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个实现的对象。理论上,通过这种方法,我们的代码将完全与接口实现分离,这就使得我们可以透明的将某个实现替换为另一个实现。
public class Factories {
public static void serviceConsumer(ServiceFactory fact){
Service s=fact.getService();
s.menthod();
s.method2();
}
public static void main(String[] args){
serviceConsumer(new I1F());
serviceConsumer(new I2F());
}
}
interface Service{
void menthod();
void method2();
}
interface ServiceFactory{
Service getService();
}
class Im1 implements Service{
Im1(){}
@Override
public void menthod() {
System.out.println("I1menthod");
}
@Override
public void method2() {
System.out.println("I1method2");
}
}
class I1F implements ServiceFactory{
@Override
public Service getService() {
return new Im1();
}
}
class Im2 implements Service{
Im2(){}
@Override
public void menthod() {
System.out.println("I2menthod");
}
@Override
public void method2() {
System.out.println("I2method2");
}
}
class I2F implements ServiceFactory{
@Override
public Service getService() {
return new Im2();
}
}
但我们为什么要使用这种额外的间接性呢?常见原因就是使用框架。
Java编程思想之九 接口的更多相关文章
- java编程思想第九章接口
9.1抽象类和抽象方法 为什么要有抽象类? 是希望通过通用接口操作一系列类. 那么抽象类的形式是什么样的呢? 声明类的使用使用abstract关键字,且在该类中应该具有抽象方法. 注:抽象方法被关键字 ...
- Java编程思想学习(九) 异常处理
java的异常处理机制可以使程序有极好的容错性,让程序更加的健壮.所谓的异常,就是指的阻止当前方法或作用域继续执行的问题,,当程序运行时出现异常时,系统就会自动生成一个Exception对象来通知程序 ...
- Java编程思想学习笔记——接口
1.抽象类和抽象方法 抽象方法:不完整的,仅有声明而没有方法体. abstract void f(); 抽象类:包含抽象方法的类.(若一个类包含一个或多个抽象方法,则该类必须限定为抽象的.) 1.用抽 ...
- Java编程思想 第九章 接口
第九章 接口 抽象类和抽象方法 抽象:从具体事物抽出.概括出它们共同的方面.本质属性与关系等,而将个别的.非本质的方面.属性与关系舍弃,这种思维过程,称为抽象. 这句话概括了抽象的概念,而在Java中 ...
- 《Java编程思想》阅读笔记二
Java编程思想 这是一个通过对<Java编程思想>(Think in java)进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会忽略或 ...
- Java编程思想——第17章 容器深入研究(two)
六.队列 排队,先进先出.除并发应用外Queue只有两个实现:LinkedList,PriorityQueue.他们的差异在于排序而非性能. 一些常用方法: 继承自Collection的方法: add ...
- JAVA编程思想——分析阅读
需要源码.JDK1.6 .编码风格参考阿里java规约 7/12开始 有点意识到自己喜欢理论大而泛的模糊知识的学习,而不喜欢实践和细节的打磨,是因为粗心浮躁导致的么? cron表达式使用 设计能力.领 ...
- 《Java编程思想》读书笔记(四)
前言:三年之前就买了<Java编程思想>这本书,但是到现在为止都还没有好好看过这本书,这次希望能够坚持通读完整本书并整理好自己的读书笔记,上一篇文章是记录的第十七章到第十八章的内容,这一次 ...
- Java编程思想重点笔记(Java开发必看)
Java编程思想重点笔记(Java开发必看) Java编程思想,Java学习必读经典,不管是初学者还是大牛都值得一读,这里总结书中的重点知识,这些知识不仅经常出现在各大知名公司的笔试面试过程中,而 ...
随机推荐
- django配置文件
1.BASSE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 当前工程的根目录,Django会依 ...
- 英语chalchite蓝绿松石chalchite单词
蓝绿松石是铜和铝的磷酸盐矿物集合体,以不透明的蔚蓝色最具特色.也有淡蓝.蓝绿.绿.浅绿.黄绿.灰绿.苍白色等色.一般硬度5~6,密度2.6~2.9,折射率约1.62.长波紫外光下,可发淡绿到蓝色的荧光 ...
- android黑白屏的问题
你会很奇怪,为什么有些app启动时,会出现一会儿的黑屏或者白屏才进入Activity的界面显示,但是有些app却不会如QQ手机端,的确这里要做处理一下.这里先了解一下为什么会出现这样的现象,其实很简单 ...
- centos逻辑卷使用
要求: 1.硬盘格式成物理卷pvpvcreate/dev/sdb/dev/sda 2.创建卷组vgcreatevg1000/dev/sdb1/dev/sdb2#创建卷组”vg1000” 3.增加卷组 ...
- Linux配置swap
根据自己的物理内存分配合适的swap大小 下面是合适的配置 物理内存 交换分区(swap) <=4G 至少2G 4-16G 至少4G 16G-64 至少8G 下面是操作步骤 1.首先查看我们的内 ...
- MyBatis面试题整理
MyBatis面试题整理 1.什么是MyBatis? 答:MyBatis是一个可以自定义SQL.存储过程和高级映射的持久层框架. 2.讲下MyBatis的缓存 答:MyBatis的缓存分为一级缓存和二 ...
- Docker08-网络管理
目录 桥接网络 Bridge Network 相关操作命令 实例演示:容器之间通过自定义bridge通讯 宿主网络 Host Network Overlay Network 相关操作命令 实例演示:容 ...
- echarts路径图 绘制上海市52路公交车线路
busLines = [{"coords":[[121.494687,31.253937],[121.494276,31.254031],[121.494226,31.254042 ...
- Django之auth认证
Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的 ...
- Redis持久化 - RDB和AOF
原文:https://segmentfault.com/a/1190000016021217 一.持久化的作用 1. 什么是持久化 持久化(Persistence),即把数据(如内存中的对象)保存到可 ...