Java学习(五)-接口

  1. 接口概念
    Java程序设计语言中,接口不是类,二十对象的一组需求描述,这些类需要遵从接口描述统一格式进行定义。
    接口中的所有方法自动地属于public。因此,在接口中声明方法时,不必提供关键字public
    接口中还可以定义常量,但是接口中决不能含有实例域,在Java SE 8之前,也不能在接口中实现方法。
    提供实例域和方法实现的任务应该由实现接口的那个类完成。因此,可以将接口看成是没有实例域的抽象类。但是这两个概念还是有一定区别的。

    (1)接口的特性
    接口不是类,尤其不能使用new运算符实例化一个接口:

    x = new Comparable(...);//ERROR
    

    然而,尽管不能构造接口的对象,却能声明接口变量:

    Comparable x;
    

    与接口中的方法都自动地被设置为public一样,接口中的域被自动的设置为public static final
    有些接口只定义了常量,而没有定义方法。例如,在标准库中有一个SwingConstants就是一个这样的接口,其中包含了NORTHSOUTH等常量。任何实现SwingConstants接口的类都自动地继承了这些常量,并可以在方法中直接引用NORTH,而不必采用SwingConstants.NORTH这样繁琐书写形式。
    尽管每个类智能拥有一个超类,但却可以实现多个接口。这就为定义类的行为提供的极大的灵活性。
    (2)接口与抽象类
    为什么Java程序设计语言还要不辞辛苦地引入接口的概念?为什么不将Comparable直接设计成如下所示的抽象类。

    abstract class Comparable {
    	public abstract int compareTo(Object other);
    }
    

    然后,Employee类再直接扩展这个抽象类,并提供compareTo方法的实现:

    class Employee extends Comparable {
    	public int compareTo(Object other){...};
    }
    

    使用抽象类表示通用属性存在这样一个问题:每个类智能扩展于一个类。假设Employee类已经扩展于一个类,例如Person,它就不能再扩展第二个类了。
    但每个类可以实现多个接口。
    (3)静态方法
    Java SE 8,允许在接口中增加静态方法。理论上讲,没有任何理由任务这是不合法的。只是有违于将接口作为抽象规范的初衷。
    (4)默认方法
    可以为接口方法提供一个默认的实现。必须用default修饰符标记这样一个方法。

    public interface Comparable<T> {
    	default int compareTo(T other) {return 0};
    }
    

    子类不用必须实现compareTo方法。
    (5)解决默认方法冲突
    如果现在一个接口中将一个方法定义为默认方法,然后又在超类或另一个接口中定义了同样的方法:
    1)超类优先。如果超类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略。
    2)接口冲突。如果一个超类接口提供了一个默认方法,另一个接口提供了一个同名而且参数类型相同的方法,必须覆盖这个方法来解决冲突。

    interface Named {
    	default String getName() {
    		return getClass().getName() + " _" + hashCode();
    	}
    }
    
    class Student implements Person, named {
    	...
    }
    

    Student类会继承PersonNamed接口提供的两个不一致的getName方法。并不是从中选择一个,Java编译器会报告一个错误,让程序员来解决这个二义性。只需要在Student类中提供一个getName方法。在这个方法中,可以选择两个冲突方法中的一个:

    class Student implements Person, Named {
    	public String getName() {
    		return Person.super.getName();
    	}
    }
    

    (6)接口与回调
    回调是一种常见的程序设计模式。在这种模式中,可以指出某个特定时间发生时应该采取的动作。
    (7)对象克隆
    要了解克隆具体含义,先来回忆为一个包含对象引用的变量建立副本时会发生什么。原变量和副本都是同一个对象的引用。这说明任何一个变量改变都会影响另一个变量。

    Employee original = new Employee("John public", 50000);
    Employee copy = original;
    copy.raiseSalary(10);
    //如果希望copy是一个新对象,它的初始状态与original相同,但是之后它们各自会有自己不同的状态,这种情况下就可以使用clone方法。
    Employee copy = original.clone();
    copy.raiseSalary(10);
    

    不过并没有这么简单。clone方法是Object的一个protected方法,这说明你的代码不能直接调用这个方法。只有Employee类可以克隆Employee对象。这个限制是有原因的。想想看Object类如何实现clone。它对于这个对象一无所知,所以只能逐个域地进行拷贝。如果对象中所有数据域都是数值或其他基本类型,拷贝这些域没有任何问题。但是如果对象包含子对象的引用,拷贝域就会得到相同子对象的另一个引用,这样一来,源对象和克隆对象仍然共享一些信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值