向上转型与向下转型(超详细)

article/2025/10/3 7:47:38

本文利用代码例子解释向上转型与向下转型,文末有举例整合原代码。


首先,我们要知道:转型发生在继承后,也就是父类子类存在的前提下。其次,我们要清楚:向下转型的前提是已经发生了向上转型,向下转型是再次转回来而已。最后,我们要明白:向上转型和向下转型都有三种方法:直接赋值、作为参数和作为返回值类型。另外,我们要注意:向下转型要用到强制类型转换,从而完成接收。


定义三个类:Animals 类、NiuMa 类、A 类:

class Animals{  //Animals类,作为父类public void eat1(){System.out.println("几乎都是肉食动物");}
}class NiuMa extends Animals{   //NiuMa类:作为子类public void eat2(){System.out.println("杂食动物");}public void sleep(){System.out.println("都要睡觉。");}
}class A{    //A类:作为参数和返回类型要用到。public void func1(Animals animals){animals.eat1();System.out.println("父类形参");}public void func3(NiuMa niuMa){niuMa.sleep();System.out.println("子类形参");}public NiuMa func2(){System.out.println("此时返回值类型与public后的引用类型一致");return new NiuMa();}   public Animals func4(){System.out.println("此时返回值类型与public后的引用类型不一致!");return new NiuMa();}public Animals func5(){System.out.println("此时返回值类型与public后的引用类型一致");return new Animals();}public NiuMa func6(){System.out.println("此时返回值类型与public后的引用类型不一致!");return (NiuMa)new Animals();}
}

Animals 类:作为父类,具有公共方法 eat1() 。

NiuMa 类:作为子类,具有子类独有方法 sleep() 。

A 类:作为其他类,要借助该类实现参数类型和返回值类型的转型。


向上转型:

一、直接赋值法:

class Text{public static void main(String[] args) {Animals people1 = new NiuMa();people1.eat1();//调用继承后公共部分的方法,没重写调用没重写的,重写了调用重写后的。}
}

父类引用子类对象:Fu dui1 = new Zi();

可用该对象调用继承后公共部分的方法,若该方法被子类重写,则调用重写后的方法

二、作为参数法:

class Text{public static void main(String[] args) {NiuMa niuma1 = new NiuMa();A a1 = new A();a1.func1(niuma1);}
}

形参为父类,实参为子类。

在方法中实现向上转型,即在 func 方法中已经完成转型任务,完成调用其他方法的实现。

三、作为返回值类型法:

class Text{public static void main(String[] args) {//返回值类型法向上转型://利用func2():public后面为子类,返回值类型为子类A a1 = new A();//用引用类型直接接收:NiuMa niuma1 = a1.func2();//正常接收。Animals animals1 = a1.func2();//发生了向上转型//new对象进行接收:NiuMa niuma2 = new NiuMa();Animals animals2 = new Animals();niuma2 = a1.func2(); //正常接收animals2 = a1.func2();//发生了向上转型//利用finc4():public后面为父类,返回值类型为子类A a2 = new A();//用引用类型直接接收:NiuMa niuma3 = (NiuMa) a2.func4();//相当于发生了一次向下转型Animals animals3 = a2.func4();//正常接收。//new对象进行接收:NiuMa niuma4 = new NiuMa();Animals animals4 = new Animals();niuma4 = (NiuMa) a2.func4(); //相当于又发生了一次向下转型。animals4 = a2.func4();//正常接收//结论:当public后面为父类,返回值为子类时,实际返回值为父类类型。}
}

此块代码主要看利用 func2() 的,因为返回值类型参考的是 public 后为父类还是子类。

父类引用,接收返回类型为子类的方法,实现向上转型。


向下转型:

一、直接赋值法:

class Text{public static void main(String[] args) {Animals people2 = new NiuMa();//要先发生一次向上转型NiuMa people3 = (NiuMa) people2; //将people2强制类型转换成NiuMa类,用people3接收people1.eat1();people3.sleep();}
}

要先发生向上转换:Fu dui2 = new Zi();

向下转换:Zi dui3 = (ZI) dui3;

二、作为参数法:

class Text{public static void main(String[] args) {Animals animals1 = new NiuMa();//先发生强制类型转换A a2 = new A();a2.func3((NiuMa) animals1);}
}

形参为子类,实参为父类。

在方法中实现向下转型,即在 func 方法中已经完成转型任务,完成调用其他方法的实现。

传参时要进行强制类型转换。

三、作为返回值类型法:

public Text{public static void main(String[] args) {//返回值类型法向下转型://利用func5():public后面为父类,返回值类型为父类。A a1 = new A();//用引用类型直接接收:NiuMa niuma1 = (NiuMa) a1.func5();//发生了向下转型Animals animals1 = a1.func5();//正常接收//new对象进行接收:NiuMa niuma2 = new NiuMa();Animals animals2 = new Animals();niuma2 = (NiuMa) a1.func5();//发生了向下转型animals2 = a1.func5();//正常接收//利用func6():public后面为子类,返回值类型为父类。A a2 = new A();//用引用类型直接接收:NiuMa niuma3 = a2.func6();//正常接收Animals animals3 = a2.func6();//相当于向上转型//new对象进行接收:NiuMa niuma4 = new NiuMa();Animals animals4 = new Animals();niuma4 = a2.func6(); //正常接收animals4 = a2.func6();//相当于向上转型//小结:当public后面为子类,返回值类型为父类的时候,返回值类型为子类。}
}

此块代码主要看利用 func5() 的,因为返回值类型参考的是 public 后为父类还是子类。

子类引用,接收返回类型为父类的方法,实现向上转型,要注意进行强制类型转换。


注意点:

一、以下为错误代码:

class Text{public static void main(String[] args) {//⭐错误代码:Animals people = new Animals();A a = new A();a.func3(people);//形参只能向下兼容,不能向上兼容。向下兼容的时候传入子类则会发生向上转型。}
}

此时代码直接会报错:

因为该代码与是否发生向上转型或向下转型无关。而向下转型的本质是已经发生过向上转型,通过强制类型转换从而回来罢了,但是该处错误直接类型不匹配。

由此我们也可以得出一个结论:

形参只能向下兼容,不能向上兼容。向下兼容的时候传入子类则会发生向上转型。

二、关于返回值类型同方法上下不匹配:

在 func4() 与 func6() 中,public 后的引用类型与返回值类型不匹配,但在主函数中用某引用类型去接收该返回值的时候,一定要用 pubic 后的引用类型

三、为什么会发生向上转型和向下转型?

向上转型是为了调用父类中的方法,向下转型是为了使用完后转回子类,以此才能调用父类中没有的方法


总结:

向上转型:自动转型,父类引用子类对象。for调父类方法。

向下转型:强制类型转换,本质上就是子类已经发生了向上转型,再次转回来而已。for调父类中没有的子类方法。


以下为整合代码:

放入 Idea 里分别把 main 方法放开运行理解更深刻:

class Animals{public void eat1(){System.out.println("几乎都是肉食动物");}
}
class NiuMa extends Animals{public void eat2(){System.out.println("杂食动物");}public void sleep(){System.out.println("都要睡觉。");}
}
class A{public void func1(Animals animals){animals.eat1();System.out.println("父类形参");}public void func3(NiuMa niuMa){niuMa.sleep();System.out.println("子类形参");}public NiuMa func2(){System.out.println("此时返回值类型与public后的引用类型一致");return new NiuMa();}public Animals func4(){System.out.println("此时返回值类型与public后的引用类型不一致!");return new NiuMa();}public Animals func5(){System.out.println("此时返回值类型与public后的引用类型一致");return new Animals();}public NiuMa func6(){System.out.println("此时返回值类型与public后的引用类型不一致!");return (NiuMa)new Animals();}}
public class ZhuAn {public static void main4(String[] args) {//主要为向下转型。//返回值类型法向下转型://利用func5():public后面为父类,返回值类型为父类。A a1 = new A();//用引用类型直接接收:NiuMa niuma1 = (NiuMa) a1.func5();//发生了向下转型Animals animals1 = a1.func5();//正常接收//new对象进行接收:NiuMa niuma2 = new NiuMa();Animals animals2 = new Animals();niuma2 = (NiuMa) a1.func5();//发生了向下转型animals2 = a1.func5();//正常接收//利用func6():public后面为子类,返回值类型为父类。A a2 = new A();//用引用类型直接接收:NiuMa niuma3 = a2.func6();//正常接收Animals animals3 = a2.func6();//相当于向上转型//new对象进行接收:NiuMa niuma4 = new NiuMa();Animals animals4 = new Animals();niuma4 = a2.func6(); //正常接收animals4 = a2.func6();//相当于向上转型//小结:当public后面为子类,返回值类型为父类的时候,返回值类型为子类。}public static void main3(String[] args) {//主要为向上转型://返回值类型法向上转型://利用func2():public后面为子类,返回值类型为子类A a1 = new A();//用引用类型直接接收:NiuMa niuma1 = a1.func2();//正常接收。Animals animals1 = a1.func2();//发生了向上转型//new对象进行接收:NiuMa niuma2 = new NiuMa();Animals animals2 = new Animals();niuma2 = a1.func2(); //正常接收animals2 = a1.func2();//发生了向上转型//利用finc4():public后面为父类,返回值类型为子类A a2 = new A();//用引用类型直接接收:NiuMa niuma3 = (NiuMa) a2.func4();//相当于发生了一次向下转型Animals animals3 = a2.func4();//正常接收。//new对象进行接收:NiuMa niuma4 = new NiuMa();Animals animals4 = new Animals();niuma4 = (NiuMa) a2.func4(); //相当于又发生了一次向下转型。animals4 = a2.func4();//正常接收//结论:当public后面为父类,返回值为子类时,实际返回值为父类类型。}public static void main2(String[] args) {//传参法:在方法内实现向上转型,在方法内调用方法。//向上转型:NiuMa niuma1 = new NiuMa();A a1 = new A();a1.func1(niuma1);//向下转型:Animals animals1 = new NiuMa();//先发生强制类型转换A a2 = new A();a2.func3((NiuMa) animals1);//⭐错误代码://Animals people = new Animals();//A a = new A();//a.func3(people);//形参只能向下兼容,不能向上兼容。向下兼容的时候传入子类则会发生向上转型。}public static void main1(String[] args) {//直接赋值法//向上转型Animals people1 = new NiuMa();people1.eat1();//调用继承后公共部分的方法,没重写调用没重写的,重写了调用重写后的。//向下转型Animals people2 = new NiuMa();//要先发生一次向上转型NiuMa people3 = (NiuMa) people2; //将people2强制类型转换成NiuMa类,用people3接收people1.eat1();people3.sleep();}
}


http://chatgpt.dhexx.cn/article/XfOLOTYG.shtml

相关文章

java向上转型

我们知道按照现有类的类型来创建新类的方式为继承。 换句话说 “新类是现有类的一种类型” 因为继承可以确保父类中所有的方法在子类中也同样有效,所以能够向父类发送的所有信息也同样可以向子类发送。 这儿有一个例子: public class Test {public sta…

类中的向上转型与向下转型详解

我们的类与类之间会存在继承关系,子类继承父类,一个父类可以有多个子类,例如Animal类就可以有Cat子类,Dog子类,等等。那么我们在运用的时候根据不同的场景会出现向上转型和向下转型的情况。 一、向上转型 1、Animal a…

【基础知识】向上转型和向下转型

向上转型和向下转型的利弊 一、向上转型 好处:隐藏了子类型,提高了代码的扩展性。 坏处:只能使用父类的功能,不能使用子类特有功能,功能被限定。 使用场景:不需要面对子类型,通过提高扩展性&am…

Java向上转型的作用(有详细代码介绍)

今天看到一道Java的练习题,题目如下 当时对于主函数中 Car car (Car) new Benz(); 不是很理解,也并不知道有什么意义,因为如果仅仅写Car car new Benz(); 程序运行结果是一样的。 在经过阅读书籍和查看别的博主写的关于向上向下转型的…

MATLAB三维数组转为二维数组(时间序列分析中很有用)

在MATLAB中三维数组转二维的方法 一、写该程序的初衷 在处理时间序列遥感数据的时候,我之前的做法是: 将时间序列数据读取为三维矩阵;将该数据保存为BIP格式;在每个像元上进行循环,取出其第三维(比如有46…

Matlab一维数组及其应用

目录 1.一维数组 2.与一维数组相关的函数 3.一维数组在二维绘图中的应用 4.在已存在的图形上添加新图形 5.在一个图形窗口中绘制多个子图 6.一维数组在一元多项式运算中的应用 1.一维数组 数值数组(简称为数组)是Matlab中最重要的一种内建数据类型。数组运算是Matlab软件…

matlab 二维数组声明,Matlab字符串函数及二维数组

Matlab字符串函数及二维数组 发布时间:2017年07月28日 评论数:抢沙发 阅读数:833 strcmp(Str1,Str2),finder(S,s),strcat(S1,S2),disp(str)>> str1 str1 I am a man >> str2 str2 Iamaboy >> strcmp(str1,str2) %比较str1和str2 相同…

MATLAB 二维数组的行列操作

首先定义一个3*3的二维数组 data [1,2,3;4,5,6;7,8,9];第一列 data(:,1)第一行 data(1,:)第一列前两个数 data(1:2,1)按列展开 data(:)从第五个数到最后 data(5:end)对ADC的数据IQ分开,对应一列数据,行数据根据逗号交换 IDATAadc_data_mux(1:2:en…

复习matlab 基础知识

1、 2、a.*b就是说两个矩阵的对应元素一次相乘。 [a,b,c,d] 将数组显示。 3、for k 1:lebgth(S) 语句体 end 4、 4、while循环 while Boolean 语句体 end 5、 6、 7、break and continue break:跳出循环体,结束整个循环。 continue&#xff1a…

【Matlab编程】新手入门第三天

第三章 数组 前言1.数组的创建1.1创建多维数组 2.数组的属性2.1数组结构2.2数组大小2.3数组的维度2.4数组数据类型 3.数组操作3.1数组索引和寻址3.2数组的查找3.3数组的排序 4.关系运算和逻辑运算总结 前言 MATLAB中的数组无处不在,任何变量在MATLAB中都是以数组的…

matlab二维数组的创建及其变换

很基础的问题,但很容易忘记。。 1、MATLAB中,一般使用方括号([]),逗号(,),分号(;)与空格来创建二维数组。空数组是一种非常特殊的数组…

strptime() 函数

查看更多 https://www.yuque.com/docs/share/54ad7ca7-b9cb-4d8b-a25f-c6e3ca349648

Python中的时间函数strftime与strptime对比

这两个函数,初看真是一脸懵逼,不是同一个么,对于小萌新来说,多少有点晕菜了,随时可能把两者混淆,导致程序报错或者出现小bug,查询了几个小时,到最后才发现竟然一个字母的差别.......…

python中datetime模块中strftime/strptime函数

python中datetime模块非常好用,提供了日期格式和字符串格式相互转化的函数strftime/strptime 1、由日期格式转化为字符串格式的函数为: datetime.datetime.strftime() 2、由字符串格式转化为日期格式的函数为: datetime.datetime.strptime() 3、两个函数都涉及日期…

strftime()函数

C 库函数 : size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr) 根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。 参数说明: str -- 存储产生的结果。maxsize -- 结果可存储的最大size。fo…

strftime和strptime使用(时间日期的格式控制函数)

strftime和strptime使用 整理自《linux程序设计》 这两个函数都是时间日期的格式控制函数,在功能上看起来正好相反。strftime将一个tm结构格式化为一个字符串,strptime则是将一个字符串格式化为一个tm结构。 strftime 函数原型:size_t strfti…

符号函数与指示函数

1.符号函数——sign(x) 2.指示函数——

函数的声明和定义

一、函数声明: 1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。 2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。 3. 函数的声明一般要放在头文件中的。 二、…

main函数的一些操作

系列文章目录 第一章 OC之单例模式 第二章 OC之对象初始化 第三章 OC之类和协议 第四章 OC之main函数中的操作和一些概念 文章目录 系列文章目录前言一、main函数的一些操作二 属性和成员变量三 和isEqual四 分类和拓展五 NSString的三种类型1._NSCFConstantString2._NSCFStri…

函数的介绍

自话函数 函数这一概念,之前在数学中是最常见的。但不要忘记最初设计计算的前辈都是一些数学大家。所以函数这一概念自然也被引入到了计算机中。 数学中函数表示的一种映射关系(集合A到集合B之间的关系),而到了计算机中这一概念被延伸。 计算机中函数由…