Java中的接口

一、接口概述

接口就是一种公共的规范标准,只要符合标准,大家都可以通用

Java中的接口更多体现在对行为的抽象

二、接口的特点

1、接口用关键字interface修饰:

public interface 接口名 {}

2、类实现接口用implements表示:

public class 类名 implements 接口名 {}

3、接口不能实例化:

接口如何实例化?参照多态的方式,通过实现类对象实例化,这叫接口多态。

多态的形式:具体类多态,抽象多态,接口多态

多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象

4、接口的实现类:

要么重写接口中的所有抽象方法

要么是抽象类

5、参考代码:

package com.itheima_01;
/*
定义了一个接口 跳高
 */
public interface Jumpping {
    public abstract void jump();
}
package com.itheima_01;
/*
定义一个猫类 来实现接口
 */
//此处不能使用关键字extends (那是类与类之间的继承)
//implements 实现
public class Cat implements Jumpping{

    @Override
    public void jump(){
        System.out.println("猫可以跳高了");
    }
}
package com.itheima_01;
/*
抽象类 来实现接口时不需要重写抽象方法
    但是这个抽象类的子类在在实现方法时还是需要重写的
 */
public abstract class Dog implements Jumpping{
   /* @Override
    public void jump(){

    }*/
}
package com.itheima_01;
/*
测试类
 */
public class JumppingDemo {
    public static void main(String[] args){
        // Jumpping j = new Jumpping(); 接口也是一个抽象内容不能直接实例化

        //通过接口的实现类来  创建接口对象
        Jumpping j = new Cat();
        j.jump();
    }
}

三、接口的成员特点

1、成员变量:

只能是常量

默认修饰符:public static final

2、构造方法:

接口没有构造方法,因为接口主要是对行为进行抽象的,是没有具体存在的

一个类如果没有父类,默认继承自Object类

3、成员方法:

只能是抽象方法

默认修饰符:public abstract

关于接口中的方法,JDK8和JDK9中有一些新特性(后面再学)

4、参考代码:

package com.itheima_02;
/*
接口
 */
public interface Inter {
    //1、成员变量
    public int num = 10;
    public final int num2 = 20;
    //接口成员变量 默认语句(包括访问权限修饰符)
    //public static final int num3 = 30;  //通过颜色(IDEA中)可以看到前面可以不写
    int num3 = 30;

    //2、接口是没有构造方法的
    /*
    可以想到一点,构造方法一般就是用于 构造对象 和 初始化成员变量

    1、对于初始化成员变量而言:接口中的成员变量默认就是 静态且最终态,即无需初始化!
    可以说没有具体存在

    2、对于构造对象:
    其一,本类无法直接构造对象。
    其二,在实现类(类比子类)调用构造函数时执行默认语句super();
    可以调用超类(Object)   一个类有父类间接继承Object 无父类直接继承Object
     */
//    public Inter(){}

   /* //3、接口里面是不能有抽象方法的
    public void show(){}*/

    //4、接口里面可以有抽象方法
    public abstract void method();

    //在接口中 默认方法为抽象方法可以 可以省略权限修饰符和状态修饰符
    void show();

}
package com.itheima_02;
/*
接口的实现类:一般在接口名后加上Impl
 */

//public class InterImpl implements Inter{ } 等价于
public class InterImpl extends Object implements Inter{ //添加了extends Object
    //
    public InterImpl(){
        super();
    }

    //重写抽象方法
    @Override
    public void method(){
        System.out.println("method");
    }

    @Override
    public void show(){
        System.out.println("show");
    }

}
package com.itheima_02;
/*
测试类
 */
public class InterfaceDemo {
    public static void main(String[] args) {
        Inter i = new InterImpl();
//        i.num = 20;   无法修改 (在接口中成员变量默认被final修饰了)

        //为了方便测试,在类中用public来修饰的
        System.out.println(i.num);
//        i.num2 = 40;  在类中被final修饰了
        System.out.println(i.num2);

        //可以通过接口名 直接访问(所以又说明了接口中的成员变量也被static修饰了)
        System.out.println(Inter.num);
    }
}

四、接口的案例

1、猫和狗:

利用重写方法多的类(一般是 子类/实现类都是 的那个类)

package com.itheima_03;
/*
定义一个跳高接口
 */
public interface Jumpping { 
    //一个跳高的抽象方法
    public abstract void jump();
}
package com.itheima_03;
/*
定义一个抽象类来做 接口类的实现类
 */
//public abstract class Animal implements Jumpping {
public abstract class Animal {
    //成员变量
    private String name;
    private int age;

    //构造方法
    public Animal() {
    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

    //set/get/show成员方法
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return this.age;
    }

    public void show() {
        System.out.println(getName() + "," + getAge());
    }

    //定义Animal类特有的抽象方法
    public abstract void eat();
}
package com.itheima_03;
/*
定义一个猫类 继承Animal抽象类
 */
public class Cat extends Animal implements Jumpping{
    //构造方法
    public Cat(){}

    public Cat(String name, int age){
        //调用父类有参构造
        super(name, age);
    }

    //重写抽象方法
    @Override
    public void jump(){ //父类是抽象类 并且在实现接口时 拿到了jump这个抽象方法
        System.out.println("猫可以跳高了");
    }

    @Override
    public void eat(){
        System.out.println("猫吃老鼠");
    }
}
package com.itheima_03;
/*
定义一个狗类继承 Animal抽象类
 */
public class Dog extends Animal implements Jumpping{
    //构造方法
    public Dog(){}

    public Dog(String name, int age){
        //调用父类有参构造
        super(name, age);
    }

    //重写抽象方法
    @Override
    public void jump(){ //父类是抽象类 并且在实现接口时 拿到了jump这个抽象方法
        System.out.println("狗可以跳高了");
    }

    @Override
    public void eat(){
        System.out.println("狗吃骨头");
    }
}
package com.itheima_03;
/*
定义一个测试类测试 接口的使用
这种情况下:Animal类继承使得 子类在调用构造函数时可以找到父类 而无需去直接调用Object超类
!!!使用时 利用重写抽象方法最多 的类创建对象利于调用
(虽然也能够通过抽象父类来实现接口 从而使用父类引用调用重写方法,但是对于子类中的特有方法还是有点。。自己具体看。。)
 */
public class AnimalDemo {
    public static void main(String[] args){
        //定义一个猫类
        Animal a1 = new Cat();
        a1.setName("Tom");
        a1.setAge(10);
        a1.show();
        a1.eat();

        //a1.jump();    //报错

        //通过向下转型 父类引用转换为子类对象来调用(子类中重写了方法)
        //((Cat)a1).jump();

        Jumpping j1 = new Cat();
        j1.jump();

        System.out.println("---------------------");

        Animal a2 = new Cat("加菲猫", 8);
        a2.show();
        a2.eat();
        //a2.jump();    报错

        //通过向下转型 父类引用转换为子类对象来调用(子类中重写了方法)
        //((Cat)a2).jump();

        Jumpping j2 = new Cat();    //带参数也行
        j2.jump();

        System.out.println("---------------------");

        //直接使用 重写最多的本类
        Cat c = new Cat();
        c.setName("黑猫");
        c.setAge(3);
        c.show();
        c.eat();
        c.jump();

        System.out.println("---------------------");

        Cat c2 = new Cat("白猫", 6);
        c2.show();
        c2.eat();
        c2.jump();

        System.out.println("---------------------");

        //定义一个狗类
        Dog d = new Dog();
        d.setName("来福");
        d.setAge(7);
        d.show();
        d.eat();
        d.jump();

        System.out.println("---------------------");

        Dog d2 = new Dog("旺财", 6);
        d2.show();
        d2.eat();
        d2.jump();
    }
}