zoukankan      html  css  js  c++  java
  • Java学习笔记 -接口

    接口

    1.接口是引用数据类型
    2.接口是完全抽象的(抽象类是半抽象)或者也可以说接口是特殊的抽象类
    3.接口的语法: [修饰符列表] interface 接口名{}
    4.接口与接口之间, 接口与类之间都支持多继承
    5.接口只包含常量和抽象方法,所以没有构造方法
    6.接口中所有的元素都是public修饰的
    7.接口的抽象方法定义时: public abstract 修饰符可以省略

    • 接口中的常量定义时:public static final 修饰符可以省略
    • 在编译器编译的时候会自动加上

    接口的基本使用

    1.类和类之间叫做继承,类和接口之间叫做实现(可以将“实现”理解为“继承”)

    • 继承使用extends关键字完成
    • 实现使用implements关键字完成
      2.当一个非抽象的类实现接口的话,必须将接口中所有的抽象方法全部实现(覆盖)
    interface MyMaths{
            //这里要知道常量和方法都是省略了关键字的
    	double PI = 3.14;
    	int sum(int a ,int b);
    	int sub(int a, int b);
    }
    
    class MyMathsImpl implements MyMaths{
    	//方法覆盖(这里通常叫做实现)
    	public int sum(int a, int b){
    		return a + b;
    	}
    	public int sub(int a, int b){
    		return a - b;
    	}
    }
    public class InterfaceTest{
    	public static void main(String[] args){
    		//多态
    		MyMaths m = new MyMathsImpl();
    		int a = m.sum(1, 2); 
    		System.out.println(a);
    	}
    }
    

    一个类是否可以实现(继承)多个接口吗?

    可以,这种机制弥补了Java类和类只支持单继承。

    interface A{
    	void m1();
    }
    interface B{
    	void m2();
    }
    interface C{
    	void m3();
    }
    class D implements A,B,C{
    	public void m1(){
    		System.out.println("m1...");
    	}
    	public void m2(){
    		System.out.println("m2...");
    	}
    	public void m3(){
    		System.out.println("m3...");
    	}
    }
    
    public class InterfaceTest{
    	public static void main(String[] args){
    		//多态
    		//父类型引用指向子类型对象
    		A a = new D();
    		B b = new D();
    		C c = new D();
    		
    		//接口之间没有继承关系,是否可以强制类型转换(接口转型)
    		//属于骚操作,明明没有继承关系,还能转型,现阶段还是不要去记它,用处不大
    		B b1 = (B)a;
    		b1.m2();
    		
    		//如果想让a调用m2方法,还是直接向下转换成D即可
    		D d = (D)a;
    		d.m2();
    	}
    }
    

    无论向上转型还是向下转型,两种类型之间必须要有继承关系,没有继承关系编译器会报错,但是这句话不适用在接口方面。
    想要父类型引用调用子类型特有的方法,还是使用将父类型引用向下转型为子类型对象这种语法最好。

    没有继承关系的接口之间转型

    interface K{
    }
    interface M{
    }
    class E implements M{
    	
    }
    public class InterfaceTest{
    	public static void main(String[] args){
    		M m = new E();
    		K k = (K)m;
    	}
    }
    


    接口和接口之间进行强制类型转换的时候,没有继承关系,也可以强制类型转换,编译器不会报错
    但是要注意,在运行时可能会出现ClassCastException异常

    解释为什么第一个程序没有出现异常?
    • 首先,语法上即使没有继承关系,类或者接口类型(不能new接口对象)强制类型转化成其他接口编译是可以通过的
    • 但是运行期间,如果类或者接口类型所代表的实际对象没有实现其他接口,那么就会报ClassCastException异常。
    • 因此,例如第二个例子,好的写法是if(m instanceof K) K k = (K) m;

    继承和实现都存在的话,代码应该怎么写?

    extends 在前 implements 在后

    class Animal{
    	
    }
    //可飞翔的接口,接口通常提取的是行为动作
    interface Flyable{
    	void fly();
    }
    
    class Cat extends Animal implements Flyable{
    	public void fly(){
    		System.out.println("飞翔的小猫");
    	}
    }
    
    
    //如果不想让它飞,可以不实现Flyable的接口
    class Snake extends Animal{
    	
    }
    
    //想飞就插入Flyable接口
    class Pig extends Animal implements Flyable{
    		public void fly(){
    		System.out.println("飞翔的小猪");
    	}
    }
    public class Test{
    	public static void main(String[] args){
    		//多态
    		Flyable f = new Cat();
    		f.fly();
    		
    		Flyable f1 = new Pig();
    		f1.fly();
    	}
    }
    


    这个例子体现了接口“可插拔”的特点,这降低了程序之间的关联性,也就是解耦合。

    接口在开发中的作用

    • 接口是完全抽象的,
    • 面向抽象编程这样修改为:面向接口编程
    • 有了接口就有了可插拔。可插拔表示扩展力很强,不是焊死的
    • 主板和内存直接有插槽,这个插槽有接口,内存条坏了可以换下来,这个叫做高扩展性(低耦合度)
    总结一句话:

    面向接口编程,可以降低程序的耦合度,提供程序的扩展力,符合OCP原则
    接口的使用离不开多态机制

    //接口 -菜单
    public interface FoodMeau {
    
        public void shihongshi();
        public void rousi();
    
    }
    
    
    //接口的实现
    //西餐师傅
    //厨师是接口的实现者
    public class AmericanCooker implements FoodMeau{
        public void shihongshi(){
            System.out.println("西餐师傅做的西红柿炒蛋");
        }
        public void rousi(){
            System.out.println("西餐师傅做的鱼香肉丝");
        }
    }
    
    //中餐厨师
    public class ChineseCooker implements FoodMeau{
        public void shihongshi(){
            System.out.println("中餐师傅做的西红柿炒蛋,超好吃的");
        }
        public void rousi(){
            System.out.println("中餐师傅做的鱼香肉丝,超好吃的");
        }
    }
    
    //接口的调用者 -顾客
    public class Customer {
        //顾客手里有一个菜单
        //Customer has a FoodMenu
        //记住:以后凡是能够使用 has a 来描述的,统一以属性的方式存在
        //回顾:凡是能用 is a来描述的,都可以设置为继承
        private FoodMeau foodMeau;
    
        //Constructor
        public Customer() {
        }
        public Customer(FoodMeau foodMeau) {
            this.foodMeau = foodMeau;
        }
    
        //setting and getter
        public FoodMeau getFoodMeau() {
            return foodMeau;
        }
    
        public void setFoodMeau(FoodMeau foodMeau) {
            this.foodMeau = foodMeau;
        }
    
        //提供点菜的方法
        public void order(){
            FoodMeau f = getFoodMeau();
            f.shihongshi();
            f.rousi();
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            //建立厨师对象
            FoodMeau cooker1 = new ChineseCooker();
            FoodMeau cooker2 = new AmericanCooker();
            //建立顾客对象
            Customer c = new Customer(cooker1);
    
            //顾客点菜
            c.order();
            //如果想要点西餐
            c.setFoodMeau(cooker2);
            c.order();
        }
    }
    

    接口可以解耦合:

    任何一个接口都有调用者和实现者,接口可以将调用者和实现者解耦合
    调用者面向接口编写调用,实现者面向接口编写实现.
    大型项目的开发,一般都是将项目分离成一个模块一个模块的,
    模块和模块之间采用接口衔接,降低耦合度.

  • 相关阅读:
    【Java EE 学习 81】【CXF框架】【CXF整合Spring】
    【Java EE 学习 80 下】【调用WebService服务的四种方式】【WebService中的注解】
    【Java EE 学习 80 上】【WebService】
    【Java EE 学习 79 下】【动态SQL】【mybatis和spring的整合】
    【Java EE 学习 79 上】【mybatis 基本使用方法】
    【Java EE 学习 78 下】【数据采集系统第十天】【数据采集系统完成】
    【Java EE 学习 78 中】【数据采集系统第十天】【Spring远程调用】
    【Java EE 学习 78 上】【数据采集系统第十天】【Service使用Spring缓存模块】
    【Java EE 学习 77 下】【数据采集系统第九天】【使用spring实现答案水平分库】【未解决问题:分库查询问题】
    【Java EE 学习 77 上】【数据采集系统第九天】【通过AOP实现日志管理】【通过Spring石英调度动态生成日志表】【日志分表和查询】
  • 原文地址:https://www.cnblogs.com/zy200128/p/12726663.html
Copyright © 2011-2022 走看看