java之上转型与下转型对象

通常情况下,我们在创建对象的时候,声明对象名称的数据类型与创建对象的数据类型是一致的,例如:A a=new A();这里的A代表一个类型,但有些时候我们用一个父类声明对象名称,而用子类去创建对象,即用一个父类引用一个子类类型的对象,例如:

A a=new B();//A为父类,B为子类
或者
A a;//a引用上转型对象
B b=new B();
a=b;

上转型对象:是一种“特殊类型(功能受限制)”的子类对象,它强调父类的特性而忽略子类的特性。

举例:

package anmial;
//anmial为父类
public class Animal {
    public void show(){//父类方法
        System.out.println("I am a dog");
    }
}
import anmial.Animal;
//Pig为子类
public class Pig extends Animal {
    @Override
    public void show() {//重写父类方法
        System.out.println("I am a Pig");
    }
    public void shows(){//子类特有的方法
        System.out.println("我每天除了吃就是睡");
    }
}
import anmial.Animal;

public class test {
    public static void main(String[]args){
        Animal animal=new Pig();//这里的animal为上转型引用对象
        animal.show();
    }

}

输出:

从父类继承的方法中被改写的部分,成功输出。

在这里插入图片描述下面我们再尝试调用一下,子类特有的属性。

animal.shows();

结果报错:

在这里插入图片描述由此我们可以得出上转型对象具有以下特性:

<1>上转型对象只能访问从父类继承而来的属性,方法以及实例化对象时的类中定义的覆盖方法(上转型对象只能访问A中被继承的属性,方法以及B中定义的覆盖方法)。

<2>上转型对象不能访问实例化对象时所增加的成员属性和方法(上转型对象不能访问B类[子类]新增的属性和方法)。

那子类特有的属性就没有办法被调用了吗?

那当然不是!

针对于这种情况,那种情况呢?

由于上转型对象无法访问子类新增的成员属性和方法,所以在某些情况下需要将上转型对象转换成子类对象,才能访问子类新增的成员属性和方法,其实下转型对象就是一个普通的子类对象。

转换格式:

(要转换的子类数据类型)上转型对象;

还是上述实例:

import anmial.Animal;
public class test {
    public static void main(String[]args){
        Animal animal=new Pig();
        animal.show();
        ((Pig)animal).shows();//将上转型对象转换为子类对象
    }
}

输出:

子类特有方法被成功调用。

在这里插入图片描述

//这里的Pig为子类对象,animal为上转型对象
((Pig)animal).shows();//将上转型对象转换为子类对象

注意:

<1>只有针对上转型对象才能进行下转操作,非上转型对象不能进行下转操作。

<2>使用上转型对象机制的优点是体现了面对对象的多态性,增强了程序的简洁性。

在对象下转的操作过程中,需要明确知道转换的数据类型,如果下转的类型不明确或者不当,进行下转操作时,会引发ClassCastException异常。

为了避免出现异常,确保下转操作执行正确,在下转操作前需要对上转型对象进行类型判断,此时需要使用instanceof关键字。

语法格式如下:

//用来判断左边的对象引用是否属于右边的类型==左边的对象是否属于右边类型的实例
对象名 instanceof 对象所属类型

在我们上述实例中:

//上转型引用对象animal是否属于Pig
if(animal instanceof Pig)

注意:

<1>在上转型对象进行下转操作前,为了避免出现异常,一定要使用instanceof进行对象类型判断。

<2>上转型对象的本质其实还是一个子类对象,只不过是一个“限制版”的子类对象,子类对象新增的成员属性和方法不能使用而已。

<3>Aniamal类的call方法可以设计成重载的形式,如下例所示:这样通过用Animal的子类类型作为实参,这样call方法就不用进行下转型操作,传递过来的就是一个实际的子类 对象,可以调用子类特有的方法。

package TEST;
public class Aninmal {
    public  void run(){
        System.out.println("Animal中的run方法");
    }
    public void eat(){
        System.out.println("Animal中的eat方法");
    }
    public void sleep(){

        System.out.println("Animal中的sleep方法");
    }
    public void move(){
        System.out.println("Animal中的move方法");
    }
    //将实际的子类传递过来
    public static void call(Sheep sheep){//将call方法设置成重载方式
        sheep.special();
        sheep.move();
        sheep.eat();
        sheep.sleep();
    }
    public static void call(dog dog){//将call方法设置成重载方式
        dog.special();
        dog.move();
        dog.eat();
        dog.sleep();
    }
}


//dog类
class dog extends Aninmal{
    String name="小狗";
    @Override
    public void eat(){
        System.out.println(name+"在吃东西");
    }
    @Override
    public void sleep(){

        System.out.println(name+"在睡觉");
    }
    @Override
    public void move(){
        System.out.println(name+"在移动");
    }
    public void special(){
        System.out.println("这是"+name+"特有的方法");
    }
}

//Sheep类
class Sheep extends Aninmal{
    String name="绵羊";
    @Override
    public void sleep(){

        System.out.println(name+"在睡觉");
    }
    @Override
    public void eat(){
        System.out.println(name+"在吃东西");
    }
    @Override
    public void move(){
        System.out.println(name+"在移动");

    }
    public void special(){
        System.out.println("这是"+name+"特有的方法");
    }
}

//测试类
class Text {
    public static void main(String[]args){
        Aninmal sheep1=new Sheep();
        Aninmal dog1=new dog();
        Aninmal.call((Sheep) sheep1);
        Aninmal.call((dog) dog1);
    }
}

输出

这是绵羊特有的方法
绵羊在移动
绵羊在吃东西
绵羊在睡觉
这是小狗特有的方法
小狗在移动
小狗在吃东西
小狗在睡觉
  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从未止步..

谢谢你的打赏,我会继续努力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值