【Java核心技术】接口、lambda表达式与内部类

一、接口(Interface)

1.1 接口的概念

  • 接口不是类,而是符合这个接口的类的一组需求
  • 接口中的所有方法都自动是 public 方法。因此,在接 声明方法时,不必提供关键字 public
  • 接口没有实例字段,因为接口不是类(没有实例)
  • 接口实现 使用implements

下面展示 接口的例子

package 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;
    }
    @Override
    public int compareTo(Employee o) {
   
        return Double.compare(salary, o.salary);
    }
}

package Interfaces;
import java.util.*;

public class EmployeeSortTest {
   
    public static void main(String[] args) {
   
        var staff = new Employee[3];
        staff[0] = new Employee("Harry Hacker", 35000);
        staff[1] = new Employee("Carl Cracker", 75000);
        staff[2] = new Employee("Tony Tester", 30000);

        Arrays.sort(staff);

        for (Employee e : staff)
            System.out.println("name = " + e.getName() + ",salary=" + e.getName());

    }
}

现在,我们已经看到,要让一个类使用排序服务必须让它实现 compareTo 方法。这是理所
当然的,因为要向 sort 方法提供对象的比较方式。但是为什么不能在 Employee 类中直接提供一个 compareTo 方法 (而不实现 Comparable 接口) 呢?

因为java是一种强类型语言,调用方法时,编译器要检查这个方法必须存在,在sort方法中可能含有以下语句:

if(a[i].compaareTo(a[i])>0)
{
   
	//rerange a[i] and a[j]
	.....
}

编译器必须确认已a[i] 一定有一个 compareTo 方法.如果 a 是一个 Comparable 对象的数组,
就可以确保肯定有 compareTo 方法,因为每个实现 Comparable接口的类都必须提供这个方法.

注释:你可能认为,如果将 Arrays 类中的 sort 方法定义为接受一个 Comparable 数组,
倘若有人调用 sort 方法时所提供数组的元素 类型没有实现 Comparable 接口,编译器就
能报错。 遗憾的是,事 实并非如此占 实际上,sort 方法接受一个 Object[] 数组,并使
用一个笨拙的强制类型转换:

if(((Comparable) a[i]).compareTo(a[j])>0)
{
   
// rearrange a[i] and a[j]
}

如果使用 不属于一个实现了 Comparable 接口的类,虚拟机就会抛出一个异常,,

1.2 接口的属性

  • 接口不是类 不能用new实例化
x = new Comparable(...)
  • 可以声明接口变量,并且必须引用实现了这个接口的一个类对象
Comparable x;
x = new Employee(...); //provided Employee impolements Comparable
  • 可以使用instanceof 检查一个对象是否属于某个特定类一样,也可以使用instanceof 检查一个对象是否实现了某个特定的接口:
if (anObject instanceof Comparable){
   ... }
  • 扩展接口
public interface Moveable
{
   
	void move(double x, double y);
}

使用extends 关键字扩展以上接口:

public interface Powered extends Moveable
{
   
	double milesPerGallon();
}
  • 接口不包含实例字段,但是可以包含常量, 方法自动为public ,类似的,接口的字段自动为 public static final
public interface Powered extends Moveable
{
   
	double milesPerGallon();
	double SPEED_LIMIT = 95;  // a public static final constant
}
  • 可以实现多个接口
  • 接口也可以是密封的直接子类型(可以是类或接口)必须在 permits 子句中声明,或者要放在同一个源文件中。

1.3 接口和抽象类

区别每个类可以实现任意多个接口, 但只能扩展一个抽象类。

1.4 静态方法和私有方法

在 Java 9中,接口中的方法可以是 private 方法。private 方法可以是静态方法或实例方法。由于私有方法只能在接口本身的方法中使用,所以它们的用途很有限,只是作为接口中其他方法的辅助

1.5 默认方法

default 就是类不用实现该方法,就可以使用。

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

一个重要用法就是接口演化
例如,很久以前提供了这样一个Bag

public class Bag implements Conllection

后来,在 java8 中增加一个 stream 方法,那么 Bag 类就不能编译,因为它没有实现这个新方法,为接口增加一个非默认方法,不能保证源代码兼容
将方法实现为一个默认 ( default) 方法就可以解决这两个问题。Bag 类又能正常编译了。
另外如果没有重新编译而直接加载这个类,并在一个 Bag 实例上调用 stream 方法,则会调用 Collection,stream 方法。

1.6 默认方法冲突

一个接口中将一个方法定义为默认方法,然后又在超类或另一个接口中定义了同样的方法
1、扩展接口优先,如果扩展接口提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略。

package Interfaces;
public interface Person {
   
    default String speaks(){
   return "person";}
}
package Interfaces;
public interface Student extends Person {
   
    default String speaks(){
   return "student";}
}
package Interfaces;
public class InterfaceTest implements Student, Person{
   
    public static void main(String[] args) {
   
        InterfaceTest interfaceTest = new InterfaceTest();
        System.out.println(interfaceTest.speaks());
//        输出 student
    }
}

2、接口冲突 如果一个接 供了一个默认方法. 另一个接口提供了一个同名而且参数
类型相同的方法 (不论是否是默认方法),必须覆盖这个方法来解决冲突。

package Interfaces;
public interface Person {
   
    default String speaks(){
   return "person";}
}
package Interfaces;
public interface Student {
   
    default String speaks(){
   return "student";}
}

下面的代码就会报错

package Interfaces;
public class InterfaceTest implements Student, Person{
   
    public static void main(String[] args) {
   
        InterfaceTest interfaceTest = new InterfaceTest();
        System.out.println(interfaceTest.speaks());
    }
}

3、类优先 假设一个类扩展了一个超类,同时实现了一个接口,并且从超类和接口继承了相同的方法。
在这种情况下,只会考虑超类方法,接口的所有和超类相同的默认方法都会被忽略。如果返回类型不同,还会报错。

package Interfaces;
public class InterfaceTest extends Manger implements Person{
   
    public static void main(String[] args) {
   
        InterfaceTest interfaceTest = new InterfaceTest();
        System.out.println(interfaceTest.speak());
        System.out.println(interfaceTest.call());
        // 输出 Manger \n hello
    }
}
package Interfaces;
public interface Person {
   
    default String speak(){
   return "person";}
    default String call(){
   return  "hello";}
}
package Interfaces;
public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值