JAVA day08 接口(interface),多态,instanceof

1.接口(interface)

接口是一种引用数据类型。

引用数据类型:数组,类,接口。

接⼝的使⽤,它不能创建对象,但是可以被实现( implements ,类似于被继承)。

1.定义

public interface 接⼝名称 {

// 抽象⽅法
// 默认⽅法
// 静态⽅法
// 私有⽅法
}

2.抽象方法

抽象⽅法:使⽤ abstract 关键字修饰,可以省略,没有⽅法体。该⽅法供⼦类实现使⽤。

public interface InterFaceName {

public abstract void method ();
}
3.默认方法和静态方法
默认⽅法:使⽤ default 修饰,不可省略,供⼦类调⽤或者⼦类重写。
静态⽅法:使⽤ static 修饰,供接⼝直接调⽤。
public interface InterFaceName {
public default void method () {
// 执⾏语句
}
public static void method2 () {
// 执⾏语句
}
}
4.私有方法和私有静态方法
私有⽅法:使⽤ private 修饰,供接⼝中的默认⽅法或者静态⽅法调⽤
public interface InterFaceName {
private void method () {
// 执⾏语句
}
}
5.实现
类与接⼝的关系为实现关系,即 类实现接⼝ ,该类可以称为接⼝的实现类,也可以称为接⼝的⼦
类。实现的动作类似继承,格式相仿,只是关键字不同,实现使⽤ implements 关键字。
⾮抽象⼦类实现接⼝:
1. 必须重写接⼝中所有抽象⽅法。
2. 继承了接⼝的默认⽅法,即可以直接调⽤,也可以重写。
class 类名 implements 接⼝名 {
// 重写接⼝中抽象⽅法【必须】
// 重写接⼝中默认⽅法【可选】
}
6.使用
  • 抽象方法的使用:必须在实现类里重写所有的抽象方法,创建实现类对象后来调用重写后的方法。
  • 默认方法的使用:可以继承也就是实现,可以重写,⼆选⼀,但是只能通过实现类的对象来调⽤。
  • 静态方法的使用:静态与 .class ⽂件相关,只能使⽤接⼝名调⽤,不可以通过实现类的类名或者实现类的对象调⽤。
  • 私有方法的使用:
    私有⽅法:只有默认⽅法可以调⽤。
    私有静态⽅法:默认⽅法和静态⽅法可以调⽤。
    注意:如果⼀个接⼝中有多个默认⽅法,并且⽅法中有重复的内容,那么可以抽取出来,封装到私有⽅法中,供默认⽅法去调⽤。
代码说明
import day08.In01.Interface01;
import day08.In01.InterfaceTest01;

public class Main01 {
    public static void main(String[] args) {
        //主方法里创建的是InterfaceTest01的对象,调用的是实现接口Interface01,InterfaceTest01重写的m1抽象方法
        InterfaceTest01 in01 = new InterfaceTest01();
        //因为被重写,所以就可以直接调用抽象方法
        in01.m1();
        //默认方法可以继承,可以重写,二选一,但是只能通过实现类的对象来调用。
        in01.m2();
        //要使用静态方法需 接口名.方法名 调用
        Interface01.m3();

        //私有方法只能通过默认方法或者静态方法调用
        //1.私有调用 只有默认方法可以调用。
        in01.m5();//重写后的默认私有
        in01.m6();
        //2.私有静态调用 默认方法跟静态方法都能调用
        in01.m6();//里面调用了私有,还有静态私有
        Interface01.m7();//静态私有 接口名.方法名
        Interface01.m8();
    }
}
//实现类
import day08.In01.Interface01;

//实现接口 就必须重写接口里的所有抽象方法
public class InterfaceTest01 implements Interface01 {
    @Override//重写抽象方法
    public void m1() {
        System.out.println("InterfaceTest01实现接口Interface01中的抽象方法m1");
    }

    @Override//重写默认方法
    public void m2() {
        Interface01.super.m2();
        System.out.println("InterfaceTest01重写接口Interface01中的默认方法m2");
    }

    @Override//也可以重写m5
    public void m5() {
        Interface01.super.m5();
        System.out.println("开开心心快快乐乐健健康康生活");
    }
}
//接口
/*
* 接口不是类(class)
* 是引用数据类型 :数组,类,接口
* 但可以把它看做一个抽象类
* 接口不能new对象,但可以被实现(implements,可以看做被继承,但它不是继承哦)
*
* */
public interface Interface01 {
    //接口无法定义成员变量,只有静态常量默认使用public static final 修饰
    public static final int a = 10;//因为是常量所以必须初始化

    //因为看做是抽象类,所以含有抽象方法
    //抽象方法没有方法体哦
    public abstract void m1();
    //接口没有构造方法,因为不能new对象

    //jdk1.7之前 接口中含有抽象方法
    //jdk1.8就添加了默认方法跟静态方法
    //jdk1.9还添加了私有方法

    //默认方法
   public default void m2(){
        System.out.println("Interface01 的默认方法m2");
    }
    //静态方法
   public static void m3(){
        System.out.println("Interface01 的静态方法m3");
    }
    //私有方法
    private void m4(){
       //默认方法中相同部分
        System.out.println("开开心心快快乐乐健健康康");

        System.out.println("Interface01 的私有方法m4");
    }
    //1.默认私有:只有默认方法能调用
    // 当多个默认方法中有许多公共的属性,行为就可以提取到私有方法中,
    // 再在接口中的默认方法里调用私有方法,然后去主方法里调用默认方法
    //就可以使用接口中的默认私有方法了
    public default void m5(){
       //System.out.println("开开心心快快乐乐健健康康");
        m4();//调用私有方法
    }
    public default void m6(){
       // System.out.println("开开心心快快乐乐健健康康");
        m4();
        m9();//默认调用静态私有
    }

    //2.静态私有:
    //默认方法跟静态方法都能调用
    public static void m7(){
      // System.out.println("2233");

        m9();
    }
    public static void m8(){
       // System.out.println("2233");
    }
    //私有静态方法
    private static void  m9(){
       //静态方法相同部分
        System.out.println("静态相同部分2233");
    }



}

7.接口的多实现

之前学过,在继承体系中,⼀个类只能继承⼀个⽗类。⽽对于接⼝⽽⾔,⼀个类是可以实现多个
接⼝的,这叫做接⼝的 多实现 。并且,⼀个类能继承⼀个⽗类,同时实现多个接⼝。
class 类名 [ extends ⽗类名 ] implements 接⼝名 1 , 接⼝名 2 , 接⼝名 3 ... {
// 重写接⼝中抽象⽅法【必须】
// 重写接⼝中默认⽅法【不重名时可选】
}
  • 抽象方法接⼝中,有多个抽象⽅法时,实现类必须重写所有抽象⽅法。如果抽象⽅法有重名的,只需要重 写⼀次。
  • 默认方法:接⼝中,有多个默认⽅法时,实现类都可继承使⽤。如果默认⽅法有重名的,必须重写⼀次。
  • 静态方法:接⼝中,存在同名的静态⽅法并不会冲突,原因是只能通过各⾃接⼝名访问静态⽅法
  • 优先级当⼀个类,既继承⼀个⽗类,⼜实现若⼲个接⼝时,⽗类中的成员⽅法与接⼝中的默认⽅法重 名,⼦类就近选择执⾏⽗类的成员⽅法。

8.接口的多继承

⼀个接⼝能继承另⼀个或者多个接⼝,这和类之间的继承⽐较相似。接⼝的继承使⽤ extends
键字,⼦接⼝继承⽗接⼝的⽅法。 如果⽗接⼝中的默认⽅法有重名的,那么⼦接⼝需要重写⼀
次。
代码说明
//类 接口 继承 实现的关系
public class Main {
    public static void main(String[] args) {
        //父类先实现接口A,子类再继承父类
        Zi1 zi1 = new Zi1();
        zi1.A1();//调用抽象方法
        zi1.A2();//默认方法
        //Afu1111
        //InterfaceA的默认方法A2

        //子类先继承父类,再实现接口A,B,上面的方式也能实现多个接口
        Zi2 zi2 = new Zi2();
        zi2.A1();
        zi2.A2();
        //Azi222
        //InterfaceA的默认方法A2
        zi2.B1();
        zi2.B2();
        //Bzi222
        //InterfaceB的默认方法B2
        zi2.AB();//调用重写后的AB接口相同抽象方法 必须重写
        // 重写后的AB相同的抽象方法AB
        zi2.AB2();//调用重写后的AB接口相同默认方法 此时必须重写 没有重复的就可以选择是否重写
        //InterfaceA的默认方法AB2
        //重写后的AB相同的默认方法AB2


    }
}
//父类
//1.可以先让父类实现接口,再通过被继承,使子类也有接口的抽象方法跟默认方法
public class Fu1 implements InterfaceA{
    @Override
    public void A1() {
        System.out.println("Afu1111");
    }

    @Override
    public void AB() {

    }
}
//子类继承父类,也有接口的方法
public class Zi1 extends Fu1 {

}
public interface InterfaceA {

    //抽象方法
    public abstract void A1();
    //默认方法
    public default void A2(){
        System.out.println("InterfaceA的默认方法A2");
    }
    //AB接口相同抽象方法
    public abstract void AB();
    //AB接口相同默认方法
    public default void AB2(){
        System.out.println("InterfaceA的默认方法AB2");
    }

}
//父类2
public class Fu2 {
}
//2.子类2是先继承父类2,再实现接口
public class Zi2 extends Fu2 implements InterfaceA,InterfaceB{
    @Override
    public void A1() {
        System.out.println("Azi222");
    }

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

    @Override//AB接口有相同的抽象方法,就只用重写一次
    public void AB() {
        System.out.println("重写后的AB相同的抽象方法AB");
    }

    @Override//AB接口有相同的默认方法,就必须重写一次
    public void AB2() {
        InterfaceA.super.AB2();//前面的 InterfaceA也能改成B,因为方法都一样,可能内容不一样,看需求
        System.out.println("重写后的AB相同的默认方法AB2");
    }
}
public interface InterfaceB {

    public abstract void B1();

    public default void B2(){
        System.out.println("InterfaceB的默认方法B2");
    }
    //AB接口相同抽象方法
    public abstract void AB();
    //AB接口相同默认方法
    public default void AB2(){
        System.out.println("InterfaceB的默认方法AB2");

    }
}

9.当接口作为方法参数、返回值类型使用

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        Test01 t01 = new Test01();
        InterfaceAImpl in01 = new InterfaceAImpl();
        t01.method01(in01);//使用的方法参数也是接口A的实现类
        //重写的抽象方法A1

        Test02 t02 = new Test02();
        InterfaceA i = t02.method02();//用接口类型接收t02.method02();方法返回过来的数据
        System.out.println(i);//day08.In03.InterfaceAImpl@f5f2bb7  这是接口A的实现类的地址值
    }
}

//接口
public interface InterfaceA {
    //抽象方法

    public abstract void  A1();
}

//实现类
public class InterfaceAImpl implements InterfaceA{
    @Override
    public void A1() {
        System.out.println("重写的抽象方法A1");
    }
}
//将接口作为方法参数

public class Test01 {

    //成员方法

    //此时方法参数是接口A类型
    public void method01(InterfaceA a){
        a.A1();//相当于InterfaceA a = new InterfaceAImpl();
    }
}
import java.util.Arrays;

//将接口类型作为返回值
public class Test02 {

    public InterfaceA method02(){
        //返回的是一个接口A类型的  in02
        InterfaceAImpl in02 = new InterfaceAImpl();
        in02.A1();// 重写的抽象方法A1 调用实现类中的A1方法

        return in02;//对于这个in02 其实返回的是InterfaceA的实现类
    }
}


注意:

1.接⼝中,⽆法定义成员变量,但是可以定义常量,其值不可以改变,默认使⽤ public
static final 修饰。
2.接⼝中,没有构造⽅法,不能创建对象。
3.接⼝中,没有静态代码块。
4.接口和类的关系:
    类 和 类(单继承): 1 v 1  extends 继承
    接口 和 类: 没有此关系
    类 和 接口(多实现): 1 v n implements 实现
    接口 和 接口(多继承): 1 v n  extends 继承
5.接口作为方法参数和返回值使用的情况:
    1).接口作为方法参数使用:
        可以传所有实现类对象,所以具体使用的都是接口的实现类对象。
    2)接口作为返回值类型使用:
        可以返回所有实现类对象,所以具体返回的都是接口的实现类对象。

2.多态

多态是继封装、继承之后,⾯向对象的第三⼤特性。

1.定义

是指统一行为,具有多个不同表现形式。

2.多态出现的前提
    继承:必须存在父子类关系;实现;二选一
    向上造型:在多要中需要将子类型的引用赋值给父类型对象
    重写:必须 子类重写父类中的方法

3.多态的实现

⽗类类型 变量名 = new ⼦类对象 ;
变量名 . ⽅法名 ();
⽗类类型:指⼦类对象继承的⽗类类型,或者实现的⽗接⼝类型。
当使⽤多态⽅式调⽤⽅法时,⾸先检查⽗类中是否有该⽅法,如果没有,则编译错误;如果有,
执⾏的是⼦类重写后⽅法。
4.多态的好处
实际开发的过程中,⽗类类型作为⽅法形式参数,传递⼦类对象给⽅法,进⾏⽅法的调⽤,更能
体现出多态的扩展性与便利。
5.引用类型转换
分为向上造型和向下转型两种:
向上造型 多态本身是⼦类类型向⽗类类型向上转换的过程,这个过程是默认的。
⽗类类型 变量名 = new ⼦类类型();
向下转型:⽗类类型向⼦类类型向下转换的过程,这个过程是强制的。
⼦类类型 变量名 = (⼦类类型) ⽗类变量名;
6.转型的异常
为了避免 ClassCastException(类型转换异常)的发⽣,Java 提供了 instanceof 关键字,给引⽤变量做类型的校验。
变量名 instanceof 数据类型
如果变量属于该数据类型,返回 true
如果变量不属于该数据类型,返回 false
代码说明
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();//这样的是创建一个对象,实例化
        dog.age = 2;
        dog.eat();
        //null吃饭
        //骨头真好吃

        //多态
        Animal d = new Dog();
        //向上造型
        //父类 变量名 = new 子类();
        d.name = "小狗欢欢";
        d.eat();//调用的是父类,但是运行的是被子类重写过的
        //小狗欢欢吃饭
        //骨头真好吃

        System.out.println(d.age);//4  父类的成员变量

        //向下转型(强制转型)
        //int a = (int)2.1;
        if(d instanceof Dog) {//判断引用名是否是Dog类型,避免了强转出现ClassCastException ,类型转换异常这个错误
            Dog dd = (Dog) d;
            System.out.println(dd.age);//5子类的age
        }
    }
}


//父类
public class Animal {
    //成员变量
    int age = 4;
    String name;

    //成员方法
    public void eat(){
        System.out.println(name+"吃饭");
    }
    
}
//子类
public class Dog extends Animal {
    int age = 5;

    @Override
    public void eat() {
        super.eat();
        System.out.println("骨头真好吃");
    }
}

注意:

成员变量:编译看左边,运行看左边

成员方法:编译看左边,运行看右边 --> 主要是看有没有被重写,没有就运行原来的,反之运行之后的。

静态方法:编译看左边,运行看左边

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值