java之上转型与下转型对象

简介: 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);
    }
}

输出

这是绵羊特有的方法
绵羊在移动
绵羊在吃东西
绵羊在睡觉
这是小狗特有的方法
小狗在移动
小狗在吃东西
小狗在睡觉
相关文章
|
24天前
|
安全 Java 编译器
Java对象一定分配在堆上吗?
本文探讨了Java对象的内存分配问题,重点介绍了JVM的逃逸分析技术及其优化策略。逃逸分析能判断对象是否会在作用域外被访问,从而决定对象是否需要分配到堆上。文章详细讲解了栈上分配、标量替换和同步消除三种优化策略,并通过示例代码说明了这些技术的应用场景。
Java对象一定分配在堆上吗?
|
28天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
48 17
|
28天前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第22天】在Java的世界里,对象序列化和反序列化是数据持久化和网络传输的关键技术。本文将带你了解如何在Java中实现对象的序列化与反序列化,并探讨其背后的原理。通过实际代码示例,我们将一步步展示如何将复杂数据结构转换为字节流,以及如何将这些字节流还原为Java对象。文章还将讨论在使用序列化时应注意的安全性问题,以确保你的应用程序既高效又安全。
|
1月前
|
存储 Java 数据管理
Java零基础-Java对象详解
【10月更文挑战第7天】Java零基础教学篇,手把手实践教学!
29 6
|
1月前
|
Oracle Java 关系型数据库
重新定义 Java 对象相等性
本文探讨了Java中的对象相等性问题,包括自反性、对称性、传递性和一致性等原则,并通过LaptopCharger类的例子展示了引用相等与内容相等的区别。文章还介绍了如何通过重写`equals`方法和使用`Comparator`接口来实现更复杂的相等度量,以满足特定的业务需求。
24 3
|
1月前
|
存储 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第9天】在Java的世界里,对象序列化是连接数据持久化与网络通信的桥梁。本文将深入探讨Java对象序列化的机制、实践方法及反序列化过程,通过代码示例揭示其背后的原理。从基础概念到高级应用,我们将一步步揭开序列化技术的神秘面纱,让读者能够掌握这一强大工具,以应对数据存储和传输的挑战。
|
1月前
|
存储 Java 数据管理
Java零基础-Java对象详解
【10月更文挑战第3天】Java零基础教学篇,手把手实践教学!
20 1
|
1月前
|
Java 数据安全/隐私保护
java类和对象
java类和对象
26 5
|
27天前
|
存储 缓存 NoSQL
一篇搞懂!Java对象序列化与反序列化的底层逻辑
本文介绍了Java中的序列化与反序列化,包括基本概念、应用场景、实现方式及注意事项。序列化是将对象转换为字节流,便于存储和传输;反序列化则是将字节流还原为对象。文中详细讲解了实现序列化的步骤,以及常见的反序列化失败原因和最佳实践。通过实例和代码示例,帮助读者更好地理解和应用这一重要技术。
26 0
|
1月前
|
存储 前端开发 Java
你还没有对象吗?java带你创建一个吧
你还没有对象吗?java带你创建一个吧
13 0
下一篇
无影云桌面