• JavaSE之面向对象(下)


    接口

    1、概述:

    Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
    比如,一个子类需要继承多个类的全部方法,常见的继承方法无法实现,接口可以实现全部继承的目的,但并不是继承;再比如,需要从多个类中抽取共同的特征,与继承不同,而是能不能做的问题can-do。
    通俗来讲,接口就是规范。定义了一组规则,定义了“能不能”“can-do”的关系。相比来讲,继承则是“是不是”“is-a”的关系。
    

    2、接口的定义

    接口是java中的引用类型,只包含方法,接口的内部封装了各种方法。一个接口只提供契约,它让实现类负责来的每一个方法
    需要注意的是,java的引用数据类型:类、接口、数组、枚举、标注
    

    在JDK8之前,接口只运行:

    1.公共的静态常量:public static final可以省略
    2.公共的抽象方法:public abstract可以省略
    

    然而在JDK1.8中,却填入了以下两种:

    3.公共的默认方法
    4.公共的静态方法
    

    为什么JDK1.8会允许接口定义默认方法和静态方法呢?

    这是因为它违反了接口作为一个抽象标准定义的概念。
    1.静态方法:因为在标准库设计中,像Collection/Colletions或者Path/Paths这样成对的接口和类,由于类中都是静态方法,与其设计对映的API,不如将静态方法直接定义到接口中使用。
    2.默认方法:如果要在接口中定义新的方法,这样势必要考虑到兼容性。而默认方法的作用就是
    

    默认方法:

    JDK1.8引入默认方法新机制是考虑到一旦在接口中新增加一个方法。那么所有的实现类都要改变。默认方法解决了这一问题,可以再接口中增加新方法,而实现类不需要改变,并且还可以得到这个默认方法。

    String[] array = new String[] {
            "hello",
            ", ",
            "world",
    };
    List<String> list = Arrays.asList(array);
    list.forEach(System.out::println); // 这是 jdk 1.8 新增的接口默认方法
    
    //  jdk 1.8 的 Iterable 接口中的 forEach 默认方法
    package java.lang;
    
    import java.util.Objects;
    import java.util.function.Consumer;
    
    public interface Iterable<T> {
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    }
    

    默认方法的继承:
    1、单继承
    1.不覆写默认方法,直接从父接口中获取方法的默认实现。
    2.覆写默认方法,这跟类与类之间的覆写规则相类似。
    3.覆写默认方法并将它重新声明为抽象方法,这样新接口的子类必须再次覆写并实现这个抽象方法。
    2、多继承
    多个接口同时拥有同一方法名的默认方法时,实现类同时实现这多个接口,那么怎么判断实现类到底调用的是哪个接口中的默认方法呢?
    这时候我们需要在实现类内重写该方法,这样就避免了尴尬。

    接口实现

    实现类通过使用implements关键字实现对接口的调用。

    非抽象实现类实现接口:
    1. 必须重写接口内的所有抽象方法
    2. 继承接口内的默认方法,可以直接调用也可以重写。(重写时不需要default,默认的概念仅存在于接口内)
    3. 不能重写静态方法

    抽象实现类:
    1. 可以不重写接口内的所有抽象方法
    2. 继承接口内的默认方法,可以直接调用也可以重写。

    调用对应的方法

    1. 对于接口的抽象方法、默认方法,可以通过实现类对象直接调用
    2. 接口内的静态方法,可以通过 接口名.静态方法名 调用

    接口的多实现原则

    在继承体系中,一个类只能有一个父类。而对于接口的实现来说,一个类可以实现多个接口。所以,一个类可以继承一个父类并且同时实现多个接口。

    注意:
    1. 亲爹优先原则:当父类的成员方法与接口中的抽象方法重名时,子类选择父类中的成员方法执行。
    2. 必须做出选择:当多接口中出现方法签名相同的默认方法时,我们要做出选择:可以选择保留其中的一个,通过"接口名.super.方法名"选择保留的方法;或者在实现类中对有冲突的默认方法进行重写。

    接口的多继承

    一个接口能继承另一个或者多个接口,接口的继承也使用 extends 关键字,子接口继承父接口的方法。

    注意
    1. 子接口重写默认方法时,default关键字可以保留。
    2. 子类重写默认方法时,default关键字不可以保留。

    接口中元素的特点

    1. 接口中,无法定义成员变量,但是可以定义常量,其值不可以改变,默认使用public static final修饰。
    2. 接口中,没有构造方法,不能创建对象。
    3. 接口中,没有静态代码块。
    

    接口与实现类对象的多态引用

    参考多态部分

    匿名内部类

    在开发中,需要用到一个抽象类的子类的对象或一个接口的实现类的对象,而且只创建一个对象,那我们可以使用匿名内部类。由于匿名内部类只是用一次,因此可以极大地简化代码,而不需要新建一个子类。我们来看一下匿名内部类和非匿名内部类的实现。

    非匿名内部类

    abstract class Preson {
    	public abstract void run(); 
    }
    
    class Man extends Preson {
    	public void run() {
    		System.out.println("跑得快");
    	}
    }
    
    public class Main {
        public static void main(String[] args) {
            Person p = new Man();
            p.run(); // 跑得快
        }
    }
    

    我们再来看一下使用匿名内部类的代码

    匿名内部类

    abstract class Preson {
    	public abstract void run(); 
    }
    
    public class Main {
        public static void main(String[] args) {
            Person p = new Man() {
            	public void run() {
    		System.out.println("跑得快");
    			}
            }
            p.run(); // 跑得快
        }
    }
    

    通过接口实现匿名内部类

    interface Preson{
    	void run();
    }
    public class Test{
        public static void main(String[] args){
        	Person p = new Man() {
            	public void run() {
    		System.out.println("跑得快");
    			}
            }
            p.run(); // 跑得快
        }
    }
    
  • 相关阅读:
    顺序容器的操作
    C++顺序容器
    Java8实战系列一
    Java枚举的小知识点
    Java集合框架入门介绍(一)
    测试代码格式
    Eclipse通过jdbc连接sqlserver2008数据库的两种方式
    排序算法之插入排序
    排序算法之冒泡排序
    容器扩容之分摊时间复杂度分析
  • 原文地址:https://www.cnblogs.com/njuptzheng/p/13245746.html
Copyright © 2020-2023  润新知