栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

多态(前提、意义)类型转换

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

多态(前提、意义)类型转换

多态:同一事物,具有多个不同的表现形式

1.  前提

1. 继承或者实现【二选一】

2.方法的重写【意义体现:不重写,无意义】

3.父类引用指向子类对象【格式体现】

class Test {
    public static void main(String[] args) {
        // 父类的引用 stu 指向了一个 new Student() 子类对象
        Person p = new Student();     //前提1:Student继承Person
        p.sleep();  // 子类重写了父类的方法,执行的是子类自己的方法
    }
}

class Person {
    void sleep() {
        System.out.println("人正在睡觉");
    }
}

class Student extends Person {
    @Override
    void sleep() {
        System.out.println("学生正在教室里睡觉");
    }
}

2 多态的意义

查看一下代码,思考这段代码是否可以进行优化:

class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        func(dog);
        func(cat);
    }
    private static void func(Dog dog) {
        dog.eat();
    }
    private static void func(Cat cat) {
        cat.eat();
    }
}
class Dog {
    public void eat() {
        System.out.println("小狗正在啃骨头");
    }
}
class Cat {
    public void eat() {
        System.out.println("小猫正在吃鱼");
    }
}

上述代码中,根据不同的参数类型,我们定义了不同的func方法,这个方法出现了重载。但是,我们从func方法的内部实现上来看,这两个方法都是调用对象的eat方法。

其实,在上述代码里,我们可以考虑给Dog类和Cat类定义一个父类,通过传递父类参数的形式,来简化代码。

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利。

class Test {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        func(dog);
        func(cat);
    }
    private static void func(Animal animal) { // 参数只需要指定 Animal 父类即可
        animal.eat();
    }
}
class Animal{  // 定义一个 Animal 类,让Dog和Cat都继承自它
    public void eat() {
        System.out.println("动物正在吃东西");
    }
}
class Dog extends Animal {
    public void eat() {
        System.out.println("小狗正在啃骨头");
    }
}
class Cat extends Animal {
    public void eat() {
        System.out.println("小猫正在吃鱼");
    }
}
3. 多态的特点

1.属性和多态无关,编译和运营都是看等号左边的类型

2.方法调用时,编译看等号左边的变量类型,运行是看等号右边对象的具体类型

        如果要调用右边子类里定义的方法,需要强制类型转换

public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog();
        animal.eat();  // 会调用 Dog 类的 eat 方法
//        animal.watchDog();编译会报错,因为编译看左边animal类中没有watchDog()方法
        ((Dog) animal).watchDog();
    }
}

class Animal {  // 定义一个 Animal 类,让Dog和Cat都继承自它
    public void eat() {
        System.out.println("动物正在吃东西");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("小狗正在啃骨头");
    }
    public void watchDog() {
        System.out.println("小狗正在看家");
    }
}
public class Test {
    public static void main(String[] args) {
        Animal animal = new Dog();
        System.out.println(animal.type);  // 动物
    }
}

class Animal {  // 定义一个 Animal 类,让Dog和Cat都继承自它
    String type = "动物";
    public void eat() {
        System.out.println("动物正在吃东西");
    }
}

class Dog extends Animal {
    String type = "狗";
    @Override
    public void eat() {
        System.out.println("小狗正在啃骨头");
    }
}
4. getclass() 

获取对象指向的具体类型(看右边的实际类型)

Person p = new Student();

Person p2 = new Person();

System.out.println(p.getclass());  //Student

System.out.println(p2.getclass());  //Person

5. 引用数据类型转换

向上转型:

父类类型  变量名 = new 子类类型();
如:Animal a = new Cat();

Student s = new Student();

(Person) s //向上转型

Student s = new Student();

((Person) s).test();  //调用的是子类的方法

System.out.println(((Person) s).name)  //调用的是父类的属性

向下转型:

子类类型 变量名 = (子类类型) 父类变量名;
如:Student s =(Student) person; 

5.1 类型转换的意义

调用方法时,首先检查父类中是否有该方法,如果没有则编译错误。也就是说,不能调用子类拥有而父类没有的方法。因此,要调用子类特有的方法,必须做向下转型。

public class Test {
    public static void main(String[] args) {
        Animal dog = new Dog();
//        dog.watchDoor();  编译报错,调用方法时,编译时看左边的类型,是Animal,Animal类里没有 watchDoor方法
        ((Dog) dog).watchDoor();
    }
}
class Animal {
    String type = "动物";
}
class Dog extends Animal {
    public void watchDoor() {
        System.out.println("狗正在看门");
    }
}

5.2 转型的异常

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        Dog d = (Dog)a;       
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】
    }  
}

这段代码可以通过编译,但是运行时,却报出了 ClassCastException ,类型转换异常!这是因为,明明创建了Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。

为了避免ClassCastException的发生,Java提供了 instanceof 关键字,给引用变量做类型的校验,格式如下:

变量名 instanceof 数据类型 
如果变量属于该数据类型,返回true。
如果变量不属于该数据类型,返回false。

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009513.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号