文档章节

Java编程思想: 接口

fzyz_sb
 fzyz_sb
发布于 2016/07/22 19:22
字数 1078
阅读 63
收藏 6

抽象类和抽象方法

如果一个类提供一个通用的接口供不同子类继承, 它本身的实例化并没有任何意义, 那么可以使用abstract关键字限制其类为抽象类.

一个类只要出现abstract则必须为抽象类, 而抽象类中的抽象方法在子类中必须实现其定义.

abstract class A {
  public void show() {
    func();
  }
  public abstract void func();

}
public class B extends A{
  public void func() {
    System.out.println("B func");
  }
  public static void main(String[] args) {
    B b = new B();
    b.show();
  }
}

 

接口

抽象类允许在类中定义方法. 但接口比抽象类更加的抽象: 它不提供任何具体实现, 只允许创建者确定方法名,参数列表和返回类型.

所以,interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能否被向上转型为多种基类的类型,来实现某种类似多重继承变种的特性.

使用关键字interface定义接口, 使用implements实现此接口

interface A {
  void show();
}
class B implements A{
  public void show() {
    System.out.println("B show()");
  }
}
public class C {
  public static void func(A a) {
    a.show();
  }
  public static void main(String[] args) {
    B b = new B();
    // B show()
    func(b);
  }
}

备注: 接口中所有方法默认为public权限, 而且必须为public.

我们可以通过反射机制来验证接口的类为public abstract:

import java.lang.reflect.*;

interface A {
  void fun1();
  void fun2();
}
class B implements A{
  public void fun1() {
    System.out.println("fun1");
  }
  public void fun2() {
    System.out.println("fun2");
  }
}
public class C {
  public static void main(String[] args) {
    try {
      // output:
      // public abstract void fun2()
      // public abstract void fun1()
      Class c1 = Class.forName("A");
      Method[] methods = c1.getDeclaredMethods();
      for (Method m: methods) {
        Class retType = m.getReturnType();
        String name = m.getName();
        String modifiers = Modifier.toString(m.getModifiers());
        if (modifiers.length() > 0)
          System.out.print(modifiers + " ");
        System.out.print(retType.getName() + " " + name + "(");
        Class[] paramTypes = m.getParameterTypes();
        for (int j = 0; j < paramTypes.length; j++) {
          if (j > 0) System.out.print(",");
          System.out.print(paramTypes[j].getName());
        }
        System.out.println(")");
      }
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
  }
}

 

完全解耦

继承有可能使得类与类之间过于紧密. 我们一般可以使用接口将接口和实现相分离.

一种实现的策略是: 定义1个接口A, 定义一个使用此接口的操作类B, 定义1个实现接口的类C, 在C中使用B, 定义N个操作类继承C, 则在C中由于存在向上转型, 则使用这N个操作类.

这种策略的一种扩展形式在于: 我们可以定义多个接口, 在同一个类中实现多个接口. 由于接口和实现可以完全分离, 这样达到完全的解耦.

interface A {
  String name();
  void show(String s);
}

class B {
  public static void func(A a, String s) {
    System.out.println(a.name());
    a.show(s);
  }
}

public class C implements A {
  public String name() {
    return getClass().getName();
  }
  public void show(String s) {
    System.out.println("C " + s);
  }
  public static void main(String[] args) {
    B.func(new C1(), "hello");
    B.func(new C2(), "world");
  }
}

class C1 extends C {
  public void show(String s) {
    System.out.println("C1 " + s);
  }
}

class C2 extends C {
  public void show(String s) {
    System.out.println("C2 " + s);
  }
}

 

Java中的多重继承

类通过实现多个接口来达到多重继承.

interface A {
  void funA();
}
interface B extends A {
  void funB();
}
interface C extends A {
  void funC();
}
interface E extends B, C {
  void funE();
}
public class D implements E {
  public void funA() {
    System.out.println("funA");
  }
  public void funB() {
    System.out.println("funB");
  }
  public void funC() {
    System.out.println("funC");
  }
  public void funE() {
    System.out.println("funE");
  }
  public static void main(String[] args) {
    D d = new D();
    d.funA();
    d.funB();
    d.funC();
    d.funE();
  }
}

但使用多个接口会存在如下的情况: 方法的返回值不同导致继承的类无法进行分别(对于重载来说, 返回值不同的方法依旧为同一个方法.)

interface A {
  int show();
}

interface B {
  void show();
}
public class C implements A, B {
  public int show() {
    return 1;
  }
  public void show() {

  }
  public static void main(String[] args) {
    // ERROR: int show() 和void show() 产生冲突
    C c = new C();
  }
}

出现这个问题,本身说明接口编写不够完善,需要修改接口.

 

适配接口

我们指定一个接口, 只要遵守此接口就可以调用此接口的其它方法.

例如针对Readable接口, 我们只要实现其read方法, 那么使用Scanner(其接受Readable接口)的其它方法(如hashNext, next)就可以读取其read的数据.

import java.nio.CharBuffer;
import java.util.Scanner;
import java.util.Random;

public class RandomWords implements Readable{
  private static Random rand = new Random(47);
  private static final char[] capitals =
      "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
  private static final char[] lowers =
      "abcdefghijklmnopqrstuvwxyz".toCharArray();
  private static final char[] vowels =
      "aeiou".toCharArray();
  private int count;
  public RandomWords(int count) { this.count = count;}
  public int read(CharBuffer cb) {
    if (count-- == 0)
      return -1;
    cb.append(capitals[rand.nextInt(capitals.length)]);
    for (int i = 0; i < 4; i++) {
      cb.append(vowels[rand.nextInt(vowels.length)]);
      cb.append(lowers[rand.nextInt(lowers.length)]);
    }
    cb.append(" ");
    return 10;
  }
  public static void main(String[] args) {
    Scanner s = new Scanner(new RandomWords(10));
    while (s.hasNext()) {
      System.out.println(s.next());
    }
  }
}

 

© 著作权归作者所有

fzyz_sb
粉丝 409
博文 209
码字总数 447144
作品 0
武汉
程序员
私信 提问
那些年,关于 Java 的那些事儿

版权声明:Follow your heart and intuition. https://blog.csdn.net/qq_35246620/article/details/78695893 温馨提示:本系列博文(含示例代码)已经同步到 GitHub,地址为「java-skills」,...

维C果糖
2017/12/02
0
0
大数据开发培训:0基础学习Java编程语言有哪些知识点?

Java 技术通用、高效、具有平台移植性和安全性,广泛应用于PC、数据中心、游戏控制台、科学超级计算机、移动电话和互联网等,学习Java首先要知道学习知识点有哪些。在这就用加米谷大数据培训...

加米谷大数据
2018/07/25
0
0
为什么我会弃Java,选择了Kotlin——专访《Java编程思想》作者 Bruce Eckel

点击上方“CSDN”,选择“置顶公众号” 关键时刻,第一时间送达! 这是前不久我们发布《Kotlin或将取代Java》一文之后,来自网友们的部分声音。 可以看到:作为编程语言界的老大——Java仍然...

csdnnews
2018/05/30
0
0
stream in java8

如果使用过scala,使用scala函数编程思想处理数据,那酸爽谁用谁知道。使用java老觉得不得劲,但java8借用了scala的思想,引入了函数编程思想,那就是stream,随后我们慢慢体验她的妙处。 Ja...

jacksu在简书
2018/01/30
0
0
Java编程语言:学JAVA没有基础,给你4个方向少走弯路。

Java java常常跟"企业"联系在一起, 因为具备一些很好的语言特性, 以及丰富的框架, 在企业应用中最被青睐, 你总可以听到关于J2EE, JSP, Hibernate之类的东西的讨论. 同时, java在手机领域也有...

启示录是真的
2018/05/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

idea运行spring boot(推荐)

下载idea 注册激活:http://idea.lanyus.com/ 照着网上的步骤创建spring boot,这里记录存在的坑 首先gradle需要在本地配置环境变量,配制成本地的,联网下载的话要很久很久 第一次不要使用g...

安卓工程师王恒
5分钟前
0
0
java final学习笔记

代码如下:class Circle{ double r; double pi=3.14; public Circle(double r) { this.r=r; } public void getArea() { System.out.......

hellation_
23分钟前
0
0
JavaConfig版

中心思想:去xml配置文件。 在Spirng Boot和Spring Cloud中,大量使用了注解与JavaConfig。 xml文件 对应的Java类 spring.xml SpringConfig.java spring-mvc.xml SpringMvcConfig.java web.x...

流小文
42分钟前
4
0
Go 定时器内部实现原理剖析

前言 前面我们介绍了一次性定时器Timer和周期性定时器Ticker,这两种定时器内部实现机制相同。创建定时器的协程并不负责计时,而是把任务交给系统协程,系统协程统一处理所有的定时器。 本节...

恋恋美食
47分钟前
0
0
分布式协调神器 ZooKeeper 之整体概述

ZooKeeper 最早起源于雅虎研究院的一个研究小组。当时,雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。所以,雅虎的开发人员就...

别打我会飞
48分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部