Java-Day010

你所谓的迷茫,不过是清醒的看着自己沉沦

  • 多态
  • 抽象类
  • 接口

一、多态

1、静态绑定与动态绑定

1.1、静态绑定

在编译期间完成,可以提交代码的执行效率,静态绑定的方法包括:

  • 静态方法
  • final修饰的方法
  • 构造器
  • private修饰方法
  • 用关键字super调用的方法

1.2、动态绑定(动态联编)

在执行期间判断所引用对象的实际类型,根据其类型调用其相应的方法。可以让编程更灵活,凡是降低了代码的执行效率。

重写是动态绑定的最佳实例,因为父类和子类都有相同的方法,编译时不确定要调用哪个,只有在执行是会确定。

2、多态

多态是同一个行为具有多个不同表现形式或形态的能力。

2.1、多态的三要素

  • 继承
  • 重写
  • 父类引用指向子类对象

必须同时满足这三个条件才能形成多态。

2.2、例子

public class Animal {
    public void shout(){
        System.out.println("动物叫");
    }
}
public class Dog extends Animal{
    @Override
    public void shout() {
        System.out.println("汪汪汪!!!");
    }
}
public class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵喵...");
    }
}
public class Test {
    public static void main(String[] args) {
        animalCry(new Animal());
        animalCry(new Cat());
        animalCry(new Dog());
    }

    static void animalCry(Animal animal){
        animal.shout();
    }
}
运行结果
动物叫
喵喵喵…
汪汪汪!!!

2.3、多态只能调用子类重写的父类的方法

多态只能调用子类重写的父类的方法,不能调用子类新增的方法

public class Dog extends Animal{
    @Override
    public void shout() {
        System.out.println("汪汪汪!!!");
    }

    public void function(){
        System.out.println("狗会看门");
    }
}
public class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵喵...");
    }

    public void function(){
        System.out.println("猫会爬树");
    }
}
public class Test {
    public static void main(String[] args) {
        animalCry(new Animal());
        animalCry(new Cat());
        animalCry(new Dog());
    }

    static void animalCry(Animal animal){
        animal.shout();
        animal.function();
    }
}
运行结果
在这里插入图片描述

编译出错,找不到方法

2.4、类型转化

多态现象中,子类可以自动转为父类类型,父类不能自动转换为子类类型

如果要把子类转换为父类,需要强制转换

public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat();      // 子类自动转换为父类(父类引用指向子类对象)
        Cat cat = (Cat) new Animal();   // 强制父类转换为子类(有异常)

    }

    static void animalCry(Animal animal){
        animal.shout();
    }
}
运行结果
在这里插入图片描述

父类强制转换为子类,虽然编译的时候不报错,但是运行的时候会有异常。

也就是说在继承链上的可以互相转换,可以编译通过,但是有可能发生异常。

还有一种情况,把不是继承链上的强制转换

public class Test {
    public static void main(String[] args) {
        Animal animal = new Cat();      // 子类自动转换为父类(父类引用指向子类对象)
        Cat cat = (Cat) new Animal();   // 强制父类转换为子类(有异常)
        cat = (Cat)new String();

    }

    static void animalCry(Animal animal){
        animal.shout();
    }
}
运行结果
在这里插入图片描述

非继承链上的强制转换则编译不通过。

2.5instanceof运算符

可以通过instanceof来判断一个对象是否是一个类的实例或者其子类的实例,只能用在同一条继承链上,结果为boolean类型

public class Test {
    public static void main(String[] args) {
        System.out.println(new Animal() instanceof Cat);    // false
        System.out.println(new Cat() instanceof Animal);    // true

    }
}
运行结果
false
true

可以通过这个运算符判断是否可以进行类型转换

只可以用在同一条的继承链上,非继承链上的则无法编译通过

二、抽象类

有时候一个父类的方法永远满足不了子类的需求,那么可以把父类设置为抽象类。

abstract修饰的类为抽象类,被abstract修饰的方法叫抽象方法

  • 抽象类
    • 抽象类不能实例化,只能被用来继承
  • 抽象方法
    • 没有具体方法,用来重写

抽象类除了有抽象方法外,还有成员属性以及普通方法,即使抽象类没有抽象方法也可以被声明为抽象类,防止被实例化。

1、语法格式

1.1、抽象类语法格式

[权限修饰符] abstract class 类名{

}

1.2、抽象方法语法格式

[权限修饰符] abstract 返回值类型 方法名([参数]);

2、例子

public abstract class A {
    void a1(){
        System.out.println("抽象类内的普通方法");
    }
    abstract void a2();     // 抽象类的抽象方法
}

public class B extends A {
    @Override
    void a2() {
        System.out.println("重写抽象类内的抽象方法");
    }
}
public class Test{
    public static void main(String[] args) {
        A a = new B();
        a.a1();
        a.a2();
    }
}
运行结果
抽象类内的普通方法
重写抽象类内的抽象方法

三、接口

接口就是纯的抽象类,没有了普通方法和成员变量

接口内的所有方法都是抽象方法

接口不在使用class关键字,而是使用interface关键字定义接口

接口不在使用extends关键字继承,而是使用imlements关键字实现

一个类可以实现多个接口

1、语法格式

1.1、接口的语法格式

[权限修饰符] interface 接口名{

}

1.2、接口内方法的语法格式

返回值类型 方法名([参数]);

2、例子

public interface Person {
    void sleep();
    void eating();
}
public class Student implements Person {
    @Override
    public void sleep() {
        System.out.println("学生要睡觉");
    }

    @Override
    public void eating() {
        System.out.println("饿了要吃饭");
    }
}
public class Test {
    public static void main(String[] args) {
        Person p = new Student();
        p.eating();
        p.sleep();
    }
}
运行结果
饿了要吃饭
学生要睡觉

接口内定义的方法必须实现

3、接口的特征

  • 接口中声明的属性默认为public static fina 的也只能时pub static final的

    public interface Person {
        int a = 0;
        void sleep();
        void eating();
    }
    
    public class Test {
        public static void main(String[] args) {
            Person p = new Student();
            p.eating();
            p.sleep();
            System.out.println(Person.a);
        }
    }
    
    运行结果
    饿了要吃饭
    学生要睡觉
    0
  • 接口中只能定义抽象方法,而这些方法默认也是public的,也只能时public的

  • 接口可以继承其它的接口,并添加新的属性和抽象方法

  • 接口不能实现另一个接口,凡是可以继承多个其它的接口

    public interface A {
        void a1();
        void a2();
    }
    
    public interface B {
        void b1();
        void b2();
    }
    
    public interface Person extends A,B{
        int a = 0;
        void sleep();
        void eating();
    }
    
    public class Student implements Person {
        @Override
        public void sleep() {
            System.out.println("学生要睡觉");
        }
    
        @Override
        public void eating() {
            System.out.println("饿了要吃饭");
        }
    
        @Override
        public void a1() {
            System.out.println("a1");
        }
    
        @Override
        public void a2() {
            System.out.println("a2");
        }
    
        @Override
        public void b1() {
            System.out.println("b1");
        }
    
        @Override
        public void b2() {
            System.out.println("b2");
        }
    }
    
    public class Test {
        public static void main(String[] args) {
            Person p = new Student();
            p.eating();
            p.sleep();
            p.a1();
            p.a2();
            p.b1();
            p.b2();
        }
    }
    
    运行结果
    饿了要吃饭
    学生要睡觉
    a1
    a2
    b1
    b2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值