关于JAVA核心技术(卷一)读后的思考(接口的基本知识的讨论)

Posted zzuzhouxiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于JAVA核心技术(卷一)读后的思考(接口的基本知识的讨论)相关的知识,希望对你有一定的参考价值。

接口

接口技术:这种技术主要用来描述类具有什么功能,而并不给出每个功能的具体实现。一个类可以实现一个或多个接口,并在需要接口的地方,随时使用实现了相应接口对象。

接口概念:接口不是类,而是对类的一组需求的描述,这些类要遵从接口描述的统一格式进行定义。

举个简单的例子:假设有一个类A,其中有一个sort方法是对对象数组进行排序,但要求对象所属的类必须实现了 B接口。假设B接口定义如下:

public interface B{
   int compareTo(Object other);

}

即所有实现B接口的类都必须实现compareTo方法。

其实参数不仅可以是Object类还可以是泛型类,定义如下:

public interface B<T>{
int compareTo (T other);
}

其实也可以不带类型参数的原始B类型。这样一来,后续就要进行强制类型转换了。

后面的代码中会提到强制类型转换是如何实现的。

注意:接口定义的时候是不允许定义实例域和实现方法的,可以定义常量,而在Java SE8之后,现在可以在接口中可以提供简单的方法,但是这些方法是不允许引用实例域的。

为了让类实现一个接口,通常需要这两个步骤:

1)将类声明为实现给定的接口。

2)对接口中的所有方法进行定义。

要将类生命为实现某个接口,需要使用关键字implements:

class Employee implements Comparable

这里的Employee因为使用了Compare接口,必须在类中实现CompareTo方法。假设希望根据雇员的薪水进行比较,compareTo方法的实现:

public int compareTo(Object otherObject){
  Employee other = (Employee)otherObject;
 return Double.compare(salary,other.salary);
}

这里就进行了强制类型转换,因为参数希望是泛型,但并没有使用泛型来定义,所以在方法中进行强制类型转化,使其能够调用salary。

下面给出对一个Employee类实力数组进行排序的完整代码,用于对一个员工数组排序。

package com.java.interfaces;

import java.util.*;


public class EmployeeSortTest {
    public static void main(String[] args) {
        Employee[] staff = new Employee[3];
        
        staff[0]=new Employee("Harry Hacker",35000);
        staff[1]=new Employee("Carl Cracker",75000);
        staff[2]=new Employee("Tony Tester",38000);
        
        Arrays.sort(staff);
        
        for (Employee e:staff) {
            System.out.println("name="+e.getName()+",salary="+e.getSalary());
        }
    }

}
package com.java.interfaces;

public class Employee implements Comparable<Employee>{
    private String name;
    private double salary;
    
    public Employee (String name,double salary) {
        this.name=name;
        this.salary=salary;
    }
    public String getName() {
        return name;
    }
    public double getSalary() {
        return salary;
        
    }
    public void raiseSalary(double byPercent) {
        double raise=salary*byPercent/100;
        salary+=raise;
    }
    public int compareTo(Employee other) {
        return Double.compare(salary, other.salary);
    }

}

得到的结果:

name=Harry Hacker,salary=35000.0
name=Tony Tester,salary=38000.0
name=Carl Cracker,salary=75000.0

 接口的特性

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

2)不能构造接口对象,但是可以声明接口对象,如

Comparable x;

x=new Employee(……);//接口变量必须引用实现了接口的类对象。

3)可以使用instanceof检查一个对象是否实现某个特定接口。

4)接口与建立类的继承关系一样,接口也可以被扩展。可以允许存在多条从具有较高通用性的接口到较高专用型的接口的链。

即:接口可以继承接口来对其进行扩展。

5)接口中的方法和域都会自动设为public,但是在类中实现时,必须是public。

 

 

接口与抽象类

能够发现接口和抽象类之间是有点类似的,接下来就总结一下,接口和抽象类之间的关系。

1)为何不将接口中的方法放到抽象类中进行实现呢?

因为如果一个类只能扩展于一个类,就不能扩展于第二个类了。

2)普通类如果实现一个接口,那么普通类需要重写接口中的所有方法,但是抽象类实现接口,只需重写几个方法就可以了,子类继承抽象类后重写的方法就是抽象类在接口中所剩下并未重写的方法。

 

 

默认方法

可以为接口方法提供一个默认实现。

这样可以不用将每个方法进行重写,这样可以在类中重写需要重写的方法就可以了,类似于在抽象类中选择方法进行重写。

代码实现:

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

默认方法重要用法是“接口演化”

假设有一个类引用了一个接口,但是后来有人在接口中增加了一个新的方法,假设该方法不是默认方法,则现在这个类就无法编译了,如果不编译这个类,仍然使用这个原先的包含这个类的jar文件是不会报错,仍可正常加载的,但是如果将新增方法设为默认方法就可以完美解决这个问题了。

对于解决默认方法冲突的问题:

1)超类优先。

2)接口冲突,为了排除二义性,要在类中进行重写。

 

以上是关于关于JAVA核心技术(卷一)读后的思考(接口的基本知识的讨论)的主要内容,如果未能解决你的问题,请参考以下文章

关于JAVA核心技术(卷一)读后的思考(回调,clone的讨论)

关于JAVA核心技术(卷一)读后的思考(内部类的讨论)

关于JAVA核心技术(卷一)读后的思考(equals方法的讨论)

关于JAVA核心技术(卷一)读后的思考(用户自定义类,静态域和静态方法的思考以及方法参数)

关于JAVA核心技术(卷一)读后的思考(泛型数组列表的讨论)

关于JAVA核心技术(卷一)读后的思考(lambda表达式的讨论)