CodeGym /课程 /Java 核心 /类型转换。拓宽和窄化转换

类型转换。拓宽和窄化转换

Java 核心
第 4 级, 课程 3
可用

“嗨,阿米戈!今天课程的主题是拓宽和窄化类型转换。你很久以前就学了拓宽和窄化原始类型。第 10 级。今天我们要讲讲它如何用于引用类型,也就是类的实例。”

实际上,这一块相当简单。想象下类的继承链:类、父类、父类的父类等,一直回溯到 Object 类。由于一个类包含它所继承类的所有成员方法,因此这个类的实例可以保存在其类型是任何一个父类类型的变量中。

下面是一个示例:

代码 说明
class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
这里有三个类声明:Animal、Cat 和 Tiger。Cat 继承 Animal。Tiger 继承 Cat。
public static void main(String[] args)
{
Tiger tiger = new Tiger();
Cat cat = new Tiger(); Animal animal = new Tiger(); Object obj = new Tiger();
}
Tiger 对象可始终赋给类型是其父类类型的变量。对于 Tiger 类,分别是 Cat、Animal 和 Object。

现在我们来看一下拓宽和窄化转换。

如果赋值操作使我们在继承链中向上移动(靠近 Object 类),那么我们正在处理拓宽转换(也称为向上转换)。如果我们沿着对象类型的链向下移动,那么这就是窄化转换(也称为向下转换)。

沿继承链上移称为拓宽,因为它趋向更为普遍的类型。不过,这样我们就无法调用通过继承添加到该类的方法。

代码 说明
public static void main(String[] args)
{
Object obj = new Tiger();
Animal animal = (Animal) obj; Cat cat = (Cat) obj; Tiger tiger = (Tiger) animal; Tiger tiger2 = (Tiger) cat;
}
窄化类型时,你要使用类型转换运算符,即我们执行显式转换。

这就造成 Java 机器检查对象是否确实继承我们要转换到的类型。

这个小小的创新极大减少了类型转换错误数量,并且显著提高了 Java 程序的稳定性。

4
任务
Java 核心, 第 4 级, 课程 3
已锁定
Code entry
Your attention, please! Now recruiting code entry personnel for CodeGym. Turn up your focus, let your fingers relax, read the code, and then... type it into the appropriate box. Code entry is far from a useless exercise, though it might seem so at first glance: it allows a beginner to get used to and remember syntax (modern IDEs seldom make this possible).
代码 说明
public static void main(String[] args)
{
Object obj = new Tiger();
if (obj instanceof Cat)
{
Cat cat = (Cat) obj;
cat.doCatActions();
}}
更重要的是,使用 instanceof 检查
public static void main(String[] args)
{
Animal animal = new Tiger();
doAllAction(animal);

Animal animal2 = new Cat();
doAllAction(animal2);

Animal animal3 = new Animal();
doAllAction(animal3);
}

public static void doAllAction(Animal animal)
{
if (animal instanceof Tiger)
{
Tiger tiger = (Tiger) animal;
tiger.doTigerActions();
}

if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
cat.doCatActions();
}

animal.doAnimalActions();
}
这就是原因所在。看看左侧的示例。

我们(我们的代码)并不总是了解我们使用的对象类型。它可能是与变量 (Animal) 相同类型的对象,也可能是后代类型 (Cat,Tiger) 的对象。

不妨考虑 doAllAction 方法。无论所传递的对象类型如何,它都可以正常运行。

换句话说,它可正确处理全部三种类型:Animal、Cat 和 Tiger。

public static void main(String[] args)
{
Cat cat = new Tiger(); Animal animal = cat; Object obj = cat;
}
这里有三个赋值运算。这些都是拓宽转换的例子。

这里不需要类型转换运算符,因为根本不需要检查。对象引用始终存储在其类型是祖先类型的变量中。

“哦,倒数第二个例子清楚地说明了一切:为何需要检查,以及为何需要类型转换。”

“我希望如此。我要提醒你注意这一点:“

这些都不会导致对象发生任何变化!唯一变化的是特定引用变量上可调用的方法数量。

例如,Cat 变量可让你调用 doAnimalActions 和 doCatActions 方法。即使它指向 Tiger 对象,它也对 doTigerActions 方法一无所知。

“好,我明白了。这比我想象的要容易。”

评论 (16)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Qin-1999 级别 22
11 一月 2024
这是什么格式啊!!

class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
Qin-1999 级别 22
11 一月 2024

class Animal{public void doAnimalActions();}
class Cat extends Animal{public void doCatActions();}
class Tiger extends Cat{public void doTigerActions();}
还不如这么写
Qin-1999 级别 22
11 一月 2024

class Animal{public void doAnimalActions();}class Cat extends Animal{public void doCatActions();}class Tiger extends Cat{public void doTigerActions();}
一行写完算了
OldDog-Z124 级别 22,Germany,中国 Expert
7 九月 2023
1. 这些都不会导致对象发生任何变化!唯一变化的是特定引用变量上可调用的方法数量。
eupjcj 级别 1,China,China
5 十月 2023
求教下“特定引用变量上可调用的方法数量”是怎么变化的?
To be brave #10900452 级别 14,Пекин,China
26 一月 2022
多态
Yingjie Guan 级别 18,Quarry Bay
9 八月 2021
Object obj = new Tiger(); 这个是窄化吧,因为赋值后继承连向下移动了
z18335776829 级别 19,China,China
10 五月 2023
Object 是所有类的超类 Object是Animal的基类 Animal是Pet的基类 Pet是Cat的基类 Cat是Tiger的基类 也就说 几乎所有创建的类 都可以将实例的引用存放在 Object 类型的变量中
枫行 级别 41,China,China
30 九月 2023
错误的 Object是所有继承链的最上层
Tom 级别 41,San Jose,Sweden
4 二月 2021
老虎本來就是貓科動物
Kou Shikyo 级别 20,Tokyo
8 十月 2020
Tiger extends Cat 外国人都是这么想的??
kyrie 级别 18,重庆
11 六月 2021
。。。。遭不住 老虎本来就是猫科动物 Cat 指猫科
Tim Dai 级别 17,Tokyo,Japan
6 八月 2020
无权访问应该是语言问题。
Tim Dai 级别 17,Tokyo,Japan
7 八月 2020
Just sent email to support, let's see if it's resolved.
AE86 级别 20,Jinan
27 七月 2020
同问 只有这一节任务无权访问
吕海东 级别 20,Taiyuan,China
21 七月 2020
这一节的任务无权打开是为什么?