zoukankan      html  css  js  c++  java
  • Java基础(十)接口(interface)

      1.接口的概念

      在Java中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述。

      例如:Array类中的sort方法可以对对象数组进行排序,但要求满足下列前提:对象所属的类必须实现了Comparable接口。

      Comparable接口的代码:任何实现了Comparable接口的类都必须包含compareTo方法。

    public interface Comparable<T> {
        /**
         * Compares this object with the specified object for order.  Returns a
         * negative integer, zero, or a positive integer as this object is less
         * than, equal to, or greater than the specified object.
         *
         * @param   o the object to be compared.
         * @return  a negative integer, zero, or a positive integer as this object
         *          is less than, equal to, or greater than the specified object.
         *
         * @throws NullPointerException if the specified object is null
         * @throws ClassCastException if the specified object's type prevents it
         *         from being compared to this object.
         */
        public int compareTo(T o);
    }

      接口中的所有方法自动地属于public,因此,在接口中声明方法时,不必提供关键字public。在实现接口时,必须把方法声明为public。

      接口没有实例,在接口中可以定义常量,也可以定义简单方法,但是这些方法不能引用实例域。

      提供实例域和方法实现的任务应该由实现接口的那个类来完成,因此,可以将接口看成是没有实例域的抽象类。

      如果希望用Array类的sort方法对Employee对象数组进行排序,那么Employee类就必须实现Comparable接口。

    public class Employee implements Comparable<Employee>
    {
    ...
       public int compareTo(Employee other)
       {
          return Double.compare(salary, other.salary);  // 使用静态的compare方法,大于等于小于时分别返回1,-1,0
       }
    }

      为什么不可以直接在Employee类中直接提供compareTo方法而不实现Comparable接口呢:这是因为Java是一种强类型(strongly typed)语言。在调用方法的时候,编译器会检查这个方法是否存在。

      Array类中的sort方法中的ComparableTimSort限制了必须有compareTo方法,从而限制了必须实现Comparable接口。

        public static void sort(Object[] a) {
            if (LegacyMergeSort.userRequested)
                legacyMergeSort(a);
            else
                ComparableTimSort.sort(a, 0, a.length, null, 0, 0);
        }

      2.接口的特性

      (1)接口不是类,不能使用new实例化一个接口

      (2)尽管不能构造接口的对象,但能声明接口的变量,接口变量必须引用实现了接口的类对象。也可以使用instanceof检查一个对象是否实现了某个特定的接口。

    Comparable x;
    x = new Employee(...);
    if (x instanceOf Comparable) ...

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

      例如:首先建立一个称为Moveable的接口

    package test;
    
    public interface Moveable {
    
        void move(double x, double y);
    }

      然后建立一个称为Powered的接口,使得这个接口继承Moveable接口:这里注意的是,虽然接口中不能包含实例域,但是却可以包含常量,与接口中的方法自动地被设置成public一样,接口中的域将被自动地设置为public static final。任何实现Powered接口的类都自动地继承了这些常量,并且可在方法中直接引用SPEED_LIMIT这个常量,而不用写成Powered.SPEED_LIMIT这种形式。

    package test;
    
    public interface Powered extends Moveable{
    
        double SPEED_LIMIT = 95;
        double milesPerGallon();
    }

      任何实现了Powered 接口的类都必须实现move方法和milesPerGallon方法:

    package test;
    
    public class Imp implements Powered{
    
        @Override
        public void move(double x, double y) {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public double milesPerGallon() {
            // TODO Auto-generated method stub
            return 0;
        }
    
    }

      3.接口的好处

      前面提到过的Comparable接口也可以用抽象类来表示,接口实现关系也可以用继承来实现,例如:

    package test;
    
    public abstract class Comparable<T> {
        
        public abstract int compareTo(T o);
    }

      Employee类来继承Comparable抽象方法后必须也必须实现compareTo方法:

    package test;
    
    public class Employee extends Comparable<Employee>{
    
        @Override
        public int compareTo(Employee o) {
            // TODO Auto-generated method stub
            return 0;
        }
    
    }

      这看起来似乎没有什么问题,但是,使用抽象类表示通用属性的时候,每个类只能扩展于一个类,即每个类只能单继承。而接口的好处是,每个类可以同时实现很多个接口。接口可以提供多重继承的大多数好处,同时还能避免多重继承的复杂性和低效性。

      4.在接口中增加静态方法和默认方法

      (1)在接口中增加静态方法

      Java SE 8 允许在接口中增加静态方法:例如,在Moveable接口中提供了静态方法move,

    package test;
    
    public interface Moveable {
    
        static void move(double x, double y) {
            System.out.println(x*y);
        };
    }

      任何继承Moveable的类不用去实现move静态方法,并且可以直接调用move方法:

    package test;
    
    public class Imp implements Moveable{
    
        public static void main(String[] args) {
            Moveable.move(10.0, 10.0);      // 打印:100.0
        }
    }

      (2)在接口中增加默认方法

      可以为接口中的方法提供一个默认实现,用default修饰符标记这样一个方法,例如,Moveable接口中有两个方法,其中move方法标记为默认方法并且实现:

    package test;
    
    public interface Moveable {
    
        int size();
        default double move(double x, double y) {
            return x*y;
        }
    }

      任何继承Moveable接口的方法,如果没有重写move方法,那么就默认该类具有接口中的默认方法。

    package test;
    
    public class Imp implements Moveable{
    
        @Override
        public int size() {
            // TODO Auto-generated method stub
            return 0;
        }
    
        public static void main(String[] args) {
            Imp test = new Imp();
            System.out.println(test.move(10.0, 10.0));  // 打印:100.0
        }
    
    }

      如果在继承Moveable接口的方法中重写了默认方法,则以重写的方法为准:

    package test;
    
    public class Imp implements Moveable{
    
        @Override
        public int size() {
            // TODO Auto-generated method stub
            return 0;
        }
        
        @Override
        public double move(double x, double y) {
            // TODO Auto-generated method stub
            return x + y;
        }
    
        public static void main(String[] args) {
            Imp test = new Imp();
            System.out.println(test.move(10.0, 10.0));  // 打印:20.0
        }
    
    }

      默认方法还可以调用任何其他方法,例如,调用同一个接口中的其他方法:

    package test;
    
    public interface Moveable {
    
        int size();
        default boolean move(double x, double y) {
            return size() == 0;
        }
    }

      任何实现Moveable接口的方法都必须实现size方法,并且还拥有move方法的默认实现:

    package test;
    
    public class Imp implements Moveable{
    
        @Override
        public int size() {
            // TODO Auto-generated method stub
            return 0;
        }
    
        public static void main(String[] args) {
            Imp test = new Imp();
            System.out.println(test.move(0.0, 100.0));  // 打印:true
        }
    
    }

      5.默认方法冲突的解决方法

      如果先在一个接口中将一个方法定义为默认方法,然后又在父类或者另一个接口中定义了同样的方法,那么该如何选择:

      (1)父类优先。如果父类提供了一个具体方法,同时接口中提供了相同的默认方法,则接口中的默认方法会被忽略。

      (2)接口冲突时要重写。如果两个接口都提供一个相同的默认方法,则同时实现这两个接口的类必须重写这个方法。

  • 相关阅读:
    快速幂&欧拉降幂
    欧拉函数
    素数打表-筛法
    多源最短路径问题(Floyd算法)
    蓝桥杯-本质上升序列
    蓝桥杯-玩具蛇
    SDUT-计算机组成原理
    取消U盘和移动硬盘的GPT保护分区
    Windows 10 上运行 photoshop 等软件出现 loadlibrary failed with error 87 的解决方法!
    做题笔记
  • 原文地址:https://www.cnblogs.com/BigJunOba/p/9329516.html
Copyright © 2011-2022 走看看