Java——超类和子类对象之间的转换

2023-11-11 05:48

本文主要是介绍Java——超类和子类对象之间的转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

继承是Java中常用的一项特性,通过继承我们可以省去很多麻烦。

而Java中超类和子类对象之间的转换则是很多新手的常遇见的难题,要是处理不好,恐怕会因为这个很特殊的问题导致一些潜在的危险,让你整整一个晚上都在调试程序以解决一个让人抓狂的java.lang.ArrayStoreException异常。 

哈哈,所谓救人一bug胜造七级浮屠,今天我们就来理一理Java中超类和子类对象之间的转换,看看它到底有什么不一样!

首先我们要了解一下转换的概念。

从子类向父类的转换称为向上转换(upcasting),通过向上转换,我们能够在编写程序时采用通用程序设计的思想,在需要使用子类对象的时候,通过把变量定义为父类型,我们可以通过一个变量,使用该父类型的所有子类型实例;从父类型向子类型的转换称为向下转换(downcasting),通过向下转换,我们能在必要的时候,将父类型变量转换成子类型变量,使用一些通过子类型才能够使用的方法。

那什么时候可以进行转换呢?

我们先来说一说向上转换,这个比较简单,而且限制还少。

还是老规矩,我们下面来看一段代码~~

来呀!!阿福,放代码~~~

                        class  Father{};class Son extends  publc  Father{    };

在上面的程序中Father为超类,son是father的子类

那如何将子类转换为超类呢?

  Father  f  =   new  Son();  //父类引用指向子类对象

 显然,这样就可以了。需要注意,new  Son()表示在在堆中分配了一段空间来存放类Son中的数据,并返回一个Son的对象,并赋值给Father的引用f,即f指向子类的对象,此时,子类的对象并没有定义一个名字。

 也就是说上面的语句等价于:

                           Son  s  =   new  Son();

                            Father  f  =  s;
注:父类不可调用子类新增的方法,即f不可调用s新增的方法。

好啦,子类转父类就是这样简单,接下来该重点看看父类转子类啦。

按理论上分析的话,父类转子类是不可以实现的。因为子类继承于父类,并新增了一些父类并没有的东西,也就是说,子类对象一般都比父类对象包含更多的东西。这样的话,子类如果访问子类新增的内容, 而这些内容父类并没有,所以就会报错。

那Java里面父类到底可不可以转子类呢?

可以!但是需要满足一个前提,即该父类对象已经指向了子类对象。

如:

                      Father  f  =   new  Son();  //父类引用指向子类对象

                      Son   s2  =  (Son)f;  //可以

                      因为当子类强制转换为父类对象时,并没有实际丢失它原有内存空间(比父类多的那些部分)

                      只是暂时不可访问,所以能再转回来。

此外,当该父类是调用子类构造器创建的时候,它也可以转换为子类。

如:

Employee b=new Manager("a",1000,2,1,225);//父类调用子类的构造器 创建了一个父类对象

这个原理其实和上面的情况一样,因为它也是父类引用指向了子类对象,因此也可以进行转换。

 当然,为了防止报ClassCastExcept异常,一般可以在前面加一条判断句 if(father instanceof Son)

                  如:

                        Father  f  =   new  Son();  //父类引用指向子类对象

                        if(father instanceof Son)

                       {

                                 Son   s2  =  (Son)f;

                      }

这样就可以避免出错。

通过上文的了解,大家可能心里已经有了一些理解,最后再提一下对象在继承关系中的改变

对象的赋值是地址标识的传递,即两个对象名共同使用同一段内存地址。在Java中,对父类与子类对象之间的赋值作了如下规定:

1、子类对象名可以赋值给父类对象名;但父类对象名不可以赋值给子类对象名。

即:父类对象名=子类对象名;

2、如果一个父类对象名已经被子类对象名所赋值,那可以将父类对象名经强制转换赋值给子类对象名。

即:子类对象名=(子类类名)父类对象名;

常用的一种形式:方法中形参用父类型,实参用子类的对象名.

总结

对类进行造型转换的应参考以下原则:
1.总是可以“父=子”赋值。此时不需要类型转换。
2.可以执行类型转换“子=(子)父”,但需要运行时进行检查。如果父类变量引用的是正确的子类型,赋值将执行。如果父类变量引用的是不相关的子类型,将会生成class castException异常。
即:如果父类的实例是在子类的实例上塑造的,“子=(子)父”时就不会抛出异常。  
如:
A 是B的父类。
A a= new B(); //父类A的对象a是在子类B的对象上塑造的。
就可以:
B b= (B)a;
3.决不能在不相关的任何类之间执行类的赋值或者类型转换。即类的造型转换仅限于有继承关系的俩个类的对象之间。

 

好啦,如果大家还是不太明白,可以试一试下面的程序,亲自上手试一试会了解得更透彻一些。

package inheritance;public class test {public static void main(String[] args) {// TODO Auto-generated method stubEmployee e;Manager boss =new Manager("Searchin",52000,2018,10,25);Employee[] staff=new Employee[3];staff[0]=boss;//子类转父类Employee b=new Manager("a",1000,2,1,225);//父类调用子类的构造器 创建了一个父类对象//Manager b=new Employee("a",1000,2,1,225);Manager a=(Manager)staff[0];//强制类型转换System.out.println(staff[0].getName());System.out.println(a.getName());boss.setBonus(5000);//staff[0].setBonus(5000);}}


 

package inheritance;import java.time.*;public class Employee
{private String name;private double salary;private LocalDate hireDay;public Employee(String name, double salary, int year, int month, int day){this.name = name;this.salary = salary;hireDay = LocalDate.of(year, month, day);}public String getName(){return name;}public double getSalary(){return salary;}public LocalDate getHireDay(){return hireDay;}public void raiseSalary(double byPercent){double raise = salary * byPercent / 100;salary += raise;}
}
package inheritance;public class Manager extends Employee
{private double bonus;public Manager(String name, double salary, int year, int month, int day){super(name, salary, year, month, day);bonus = 0;}public double getSalary(){double baseSalary = super.getSalary();return baseSalary + bonus;}public void setBonus(double b){bonus = b;}
}

 

这篇关于Java——超类和子类对象之间的转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/387964

相关文章

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

C# 比较两个list 之间元素差异的常用方法

《C#比较两个list之间元素差异的常用方法》:本文主要介绍C#比较两个list之间元素差异,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. 使用Except方法2. 使用Except的逆操作3. 使用LINQ的Join,GroupJoin