gpt4 book ai didi

java - 接口(interface)和类之间的转换

转载 作者:塔克拉玛干 更新时间:2023-11-01 22:07:11 27 4
gpt4 key购买 nike

昨天刚开始学习接口(interface),一直在做一些简单的例子,我注意到我在理解类和接口(interface)之间的转换时遇到了很多麻烦,所以我读了 Java Cast Interface to Class以及 Interfaces Oracle Java Tutorials

但是当我的书在底部给出了一个小小的评论问题时,我发现我仍然没有真正完全理解,而且我买的书没有解决方案。以下是问题(我给出了我的尝试和推理,这对某些人来说可能是错误的,所以任何帮助都是好的!)

Suppose the class Sandwich implements the Edible interface, and you are given the variable declarations


Sandwich sub = new Sandwich();

Rectangle cerealBox = new Rectangle(5, 10, 20, 30);

Edible e = null;

Which of the following assignment statements are legal?


  • e = sub;
    由于 Sandwich 类实现了接口(interface) Edible ,这没有问题。我们可以说 e = sub没有问题。 它有效
  • sub = e;
    由于我们正在尝试更改我们的对象 subSandwitch类到 interface类型,我们不能在没有类型转换的情况下做到这一点。 不行
  • sub = (Sandwich) e
    作品 !这解决了我们的老问题
  • sub = (Sandwich) cerealBox;
    我不知道..但应该工作? cerealBoxRectangle所以与 (Sandwich)我们将其转换为 sub ,它是 Sandwich 的一部分
  • e =cerealBox;
    不要这么认为。 Rectangle未实现 Edible界面就这样吧不应该工作
  • e = (Edible) cerealBox;
    工作现在。 (Edible) 就好像它实现了接口(interface)一样。
  • e = (Rectangle) cerealBox;
    不确定 .我认为这行不通,我的意思是 cerealBox是 Rectangle 类型,为什么我们将其设为 rectangle再次?
  • e = (Rectangle) null;
    完全不确定
  • 最佳答案

    您需要了解的是,每个对象都有一个具体的类。它"is"该类的一个实例,它"is"该类继承的每个类的实例,所有同时 .不仅如此,它"is"任何这些类继承的每个接口(interface)的实例,所有同时 .

    所以,假设:

     class Animal
    class Mammal extends Animal implements Suckler
    class Dog extends Mammal implements Woofer

    ...如果我创建一个 new Dog()那么该对象"is"一个 Object (因为所有对象都继承 Object ),一个 Animal , Mammal , Suckler , Dog和一个 Woofer , 所有同时 .

    但是,变量与对象不同。一个变量指向一个对象,一个变量有一个类型。类型必须与分配的对象兼容,仅此而已。

    所以:
    Suckler s = new Dog();

    有效,但从那一刻起,所有编译器都知道对象 通过 s变量 Suckler .它不知道这是一只狗;它不知道它是哺乳动物。所以我们不能去:
    Dog d = s;

    ... 因为编译器不能保证 s 指向的变量是 Dog .

    变量的类型永远不能改变。 s有类型 Suckler在它的整个生命周期中,无论如何。我们可以分配一个 SheepPigs ,但除了属于 Suckler 的操作之外,我们将无法对这些对象执行任何操作。定义。

    我将假设各种类和接口(interface)的定义如下:
     public interface Edible {
    ...
    }

    public class Sandwich implements Edible {
    ...
    }

    public class Rectangle { // note, does not implement or extend anything
    // (except Object)
    ...
    }

    所以:
    Sandwich sub = new Sandwich();
    Edible e = null;
    e = sub;

    这可以。 subSandwich , 和 Sandwich是一种 Edible .
    Sandwich sub = new Sandwich();
    Edible e = null;
    sub = e;

    这不会编译。 eEdible ,但可以有任意数量的类实现 Edible ,以及 Sandwich . sub必须是 Sandwich并且由于编译器无法确定 e是三明治,它会拒绝编译。
    Sandwich sub = new Sandwich();
    Edible e = null;
    sub = (Sandwich) e;

    这有效。正如您正确计算出的那样,类型转换告诉编译器“好吧,您不能确定 eSandwich ,但作为编码器,我告诉您它是。

    如果你这样做了,并且在运行时 e实际上是一个 Apple implements Edible ,而不是 Sandwich ,JRE 会抛出 ClassCastException .你的工作是确保这不会发生——避免强制转换是最好的方法。
    Sandwich sub = new Sandwich();
    Rectangle cerealBox = new Rectangle(5, 10, 20, 30);
    sub = (Sandwich) cerealBox;

    ...将拒绝编译。 SandwichRectangle彼此没有关系。编译器知道没有 Sandwich也是 Rectangle ,所以它拒绝编译。

    变量 sub必须始终指向 Sandwich , 和 cerealBox必须始终指向 Rectangle .唯一的办法 Rectangle可能是 Sandwich是如果 Rectangle继承 Sandwich , 或相反亦然。由于这两种情况都不是,它不会编译。

    这是假设上述声明。一个类可以实现多个接口(interface),所以如果它是 public class Sandwich implements Edible, Rectangle {...} ,此代码将起作用。
    Rectangle cerealBox = new Rectangle(5, 10, 20, 30); 
    Edible e = null;
    e = cerealBox;

    ...不会编译。一个 Rectangle不是 Edible .
    Rectangle cerealBox = new Rectangle(5, 10, 20, 30); 
    Edible e = null;
    e = (Edible) cerealBox;

    ..乍一看,你可能会认为不会编译。一个 Rectangle不是 Edible ,你不能告诉编译器它是。但是编译器不能保证没有这样的类:
    public class Flapjack extends Rectangle implements Edible { ... }

    一个 Flapjack将是一种 Rectangle这也是 Edible ,而且由于编译器不够聪明,无法知道 cerealBox不是 Flapjack ,它必须编译(它会在运行时失败)。

    一个真正聪明的编译器也许能够分析程序逻辑以查看 cerealBox已初始化为 new Rectangle() ,并且没有机会在运行时更改。但是 Java 标准没有那种复杂的静态分析。
    Rectangle作者可以保证 Square不能存在,通过将其定义为 public final class Rectangle -- final关键字禁止子类。
    Rectangle cerealBox = new Rectangle(5, 10, 20, 30); 
    Edible e = null;
    e = (Rectangle) cerealBox;

    ...不会编译。 e仍然是 Edible .您不能分配 Rectangle到它,因为 EdibleRectangle不相关。
    Edible e = null;
    e = (Rectangle) null;

    将 null 转换为 Rectangle很好,但是 eEdible ,并且您不能分配 RectangleEdible ,因为它们是不相关的类型。

    关于java - 接口(interface)和类之间的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38958600/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com