1. 类型转换

存储引用类型(类)的变量也可以转换为不同的类型。但这仅适用于单一类型层次结构。让我们看一个简单的例子。假设我们有以下类层次结构,其中下面的类继承上面的类。

类型转换

引用类型和原始类型的类型转换也被归类为扩大和缩小。

我们看到 Cat 类继承了 Pet 类,而 Pet 类又继承了 Animal 类。

如果我们这样写代码:

Animal kitten = new Cat();

这是一个扩大的类型转换。它也称为隐式转换。我们扩大了cat引用,现在它指向一个Cat对象。通过这样的类型转换,我们将无法使用kitten引用来调用Cat类中存在但Animal类中不存在的方法。

缩小转换(或显式转换)发生在相反的方向:

Cat cat = (Cat) kitten;

我们明确指出我们想要将存储在kitten变量(其类型为Animal)中的引用转换为Cat类型。



2.检查对象的类型

但是你在这里需要非常小心。如果你这样做:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

编译器会允许这段代码,但是程序运行的时候会出现错误!JVM 会抛出一个异常:

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

对Cat对象的引用只能存储在类型为 Cat 类的祖先的变量中:Pet、Animal 或 Object。

这是为什么?

这里的相关点是对象引用用于引用该对象的方法和变量。如果我们使用 Animal 变量来存储对 Cat 对象的引用,就不会有任何问题:Cat 类型始终具有 Animal 类型的变量和方法——它继承了它们!

但是如果 JVM 允许我们在 Wolf 变量中存储对 Cat 对象的引用,那么我们可能会遇到这样一种情况:我们可能会尝试使用 grayWolf 变量来调用存储在该变量中的 Cat 对象中不存在的方法. 这就是为什么这种安排是不允许的。

Java 有一个特殊的instanceof运算符,可以让您检查对象是否属于某种类型,因此是否可以存储到某种类型的变量中。它看起来很简单:

variable instanceof Type

例子:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

此代码不会导致错误 — 即使在运行时也是如此。

以下是一些说明情况的示例:

加宽类型转换 描述
Cow cow = new Whale();

这是一个经典的扩大转换——不需要类型转换运算符。Cow现在只能在对象上调用类中定义的方法Whale

cow在变量上,编译器只会让你调用它的类型(类Cow)具有的方法。

缩小类型转换
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
经典收缩转换:您需要添加类型检查和强制转换运算符。
变量Cow cow存储对对象的引用Whale
我们验证是这样的,然后进行(缩小)类型转换。或者它也被称为:
类型转换
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
您可以在不检查对象类型的情况下缩小引用类型。
如果cow变量引用的对象不是 a Whale,则将InvalidClassCastException生成 an 。


3.调用原始方法:super关键字

当覆盖父类的方法时,有时我们不想用我们自己的方法替换它,而只是想稍微补充一下。

如果能在我们的方法中调用父类的方法,然后执行一些我们自己的代码就好了。或者也许先执行我们自己的代码,然后再调用父类的方法。

而 Java 让我们做到了这一点。要调用父类的方法,请执行以下操作:

super.method(arguments);

例子:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

战时,值Pi可以大于6!当然,我们是在开玩笑,但这个例子演示了这一切是如何工作的。

这里有几个例子来澄清一些事情:

代码 描述
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
CowWhale
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
屏幕输出将是:
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

这是很难的事情。老实说,这是OOP中最难的事情之一。也就是说,您确实需要知道并理解它。