【问题标题】:How does Object.toString() work for different underlying types?Object.toString() 如何适用于不同的底层类型?
【发布时间】:2013-11-23 02:29:33
【问题描述】:

我不明白为什么这在 java 中有效:

如果我在一个对象中有一个 Integer 对象,例如:

Object myIntObj = new Integer(5);

现在如果我这样做:

System.out.println(myIntObj);

输出为:5

我现在 Integer 类有一个 toString 方法的 ovveride,但在这种情况下是不同的(我认为)。 对于多态性,如果我在“父变量”中有一个“子对象”,则该对象不会改变其真实类型(在本例中为整数)但是......它(在 Object 变量中)可以只使用对象类,那我为什么要写:

System.out.println(myIntObj);

我可以直接看到数字 5 而不是这个对象的引用?因为对象类中的toString方法默认返回的只是对象引用的字符串。

喜欢:

Object currentPlayer = new Player();
System.out.println(currentPlayer);

在这种情况下,输出是 Player 对象的引用,因为在对象类中调用了 toString 方法。

那么为什么在之前的示例中我没有看到参考,而是直接看到数字? 从逻辑上讲,多态性的规则说:如果你在“父亲”变量中有一个“孩子”对象,这个对象,在里面,remanis 相同,但他被用作对象的一个​​实例,所以他可以只使用类对象,所以只是对象的方法,所以很奇怪,我没有看到引用而是直接看到数字。

希望你明白我的意思。

【问题讨论】:

  • 是否为Player 类定义了toString()
  • 只是一个评论。将对象输出到控制台时看到的字符不是引用本身,而是哈希码。

标签: java object tostring object-to-string


【解决方案1】:

你解释你的推理的最后一段有点不正确。

那么为什么在之前的示例中我没有看到参考,而是直接看到 数字?从逻辑上讲,多态性的规则说:如果你 在“父”变量中有一个“子”对象,这个对象,在里面, remanis 是一样的,但他被当作一个对象来使用,所以他可以 只使用类对象,所以只使用对象的方法,所以是 真的很奇怪,我没有看到参考,而是直接看到数字。

开头是正确的,但我加粗的部分是你从中得出的错误结论。

你是对的,使用多态,对象确实保持它的任何类型,但是引用类型(变量的类型)定义了你可以用它做什么。但是,引用类型没有描述对象的作用

这就是多态性背后的意图。它是一种抽象,用于定义可以独立于其工作方式来完成的工作。例如,如果你有这个例子:

public class Vehicle {
    public int getWheelCount() {
        return 1;
    }
}

public class Car extends Parent {
    public int getWheelCount() {
        return 4;
    }

    public void blowHorn() {
        System.out.println("Honk honk!");
    }
}

public class Bicycle extends Parent {
    public int getWheelCount() {
        return 2;
    }
}

Car car = new Car();
car.getWheelCount();  // 4
car.blowHorn();  //"Honk honk!"

Vehicle v = new Car();
v.getWheelCount()  // 4
v.blowHorn();  // COMPILE ERROR HERE!  Unknown method

Bicycle b = new Bicycle();
b.getWheelCount();  // 2

Vehicle v = new Bicycle();
v.getWheelCount();  // 2

您可以由此得出结论,当覆盖子类中的方法时,始终会调用子版本。无论您将其称为车辆还是汽车,汽车始终是汽车。但是通过将其称为车辆,您仅限于调用在所有车辆上定义的方法。

为了将其与示例联系起来,所有Vehicle 对象都有一个轮子尺寸,因此无论是 Vehicle.getWheelCount() 还是 Car.getWheelCount(),getWheelCount() 始终是可调用的。然而,Car.getWheelCount() 是执行的,因为 Car 覆盖了它。

如果引用类型为Vehicle,则不能调用blowHorn(),因为该方法仅适用于Car。

回到你的例子,整数就是整数。

Object i = new Integer(5);
i.toString();  // 5

这会打印 5,因为 i 是整数。 Integer 类覆盖 toString。引用类型(您引用对象的类型)仅决定您可以调用哪些方法,而不决定调用该方法的哪个父/子类的版本

【讨论】:

  • 非常感谢,我从 2 年开始就开始编程,在这种情况下,每次我都进行演员表,因为我不知道当你在父亲变量中有一个子对象时,这是可能的子类调用该方法。我认为在这种情况下,子类完全忘记了,所以每次我都这样做 ((Integer)i).toString();
【解决方案2】:

通过将其定义为Object,这意味着您将只能访问在Object 类中定义的方法。

这包括toString()

因此,当您实例化 new Player() 时,您仍然只能访问来自 Object 的方法,但如果您覆盖它(如 Integer.toString() 所做的那样),您仍将获得实例化类中定义的输出。

PS:父亲 -> 父母

【讨论】:

    【解决方案3】:

    这就是覆盖方法概念的工作原理:一旦继承层次结构中的某个对象提供了一个实现,就会调用这个实现,除非它被继承层次结构更下方的另一个类覆盖。

    由于java.lang.Integer 提供了toString() 的覆盖,因此调用此覆盖而不是java.lang.Object 提供的实现。

    System.out.println(myIntObj)System.out.println(myIntObj.toString()) 之间没有区别,因为println 将在内部调用toString 对所有它不知道如何打印的对象。

    Player 类行为不同的原因是它没有覆盖 toString()。如果是这样,您将看到打印的结果。但是,在没有覆盖的情况下,会调用java.lang.Object 提供的默认实现,它会打印一些通用对象信息。

    【讨论】:

      【解决方案4】:
      Object myIntObj = new Integer(5);
      

      在这里,您正在创建一个新的 Integer 实例,而不是一个空的 Object 实例。您将其分配给Object 引用的事实不会将其转换为裸Object。它仍然是Integer,但您可以将其引用为Object,因为它扩展了Object。因此,当您调用myIntObj.toString() 时,您正在调用该实例的toString() 方法。该实例原来是一个Integer 实例。于是Integer.toString() 被调用了。


      Object currentPlayer = new Player();
      

      在这种情况下,调用currentPlayer.toString() 时适用相同的规则:您实际上是在调用Player.toString()。如果Player 类没有覆盖toString(),则调用第一个升序父类toString() 实现。如果Player 直接扩展Object,则调用Object.toString(),但如果例如Player extends HumanHuman extends Object,则如果存在Human.toString(),则将调用它。如果没有,那么Object.toString()

      【讨论】:

        【解决方案5】:

        考虑这种情况,其中 Employee 有一个子类 Manager,该子类的方法 getDetails() 被覆盖,

        Employee e=new Employee();
        Employee m=new Manager();
        

        如果您调用 e.getDetails(),您将获得与 Employee 关联的行为。

        如果您调用 m.getDetails(),您将获得与 Manager 关联的行为。

        通常,您会获得与变量在运行时所引用的对象相关联的行为。这种行为通常被称为虚拟方法调用。

        因此,当您的引用是一个对象时,您获得与 Integer 关联的行为的原因是因为您在运行时引用了一个 Integer 对象。

        【讨论】:

        • 谢谢,但是为什么如果我做 m.aMethodofManagerClass() eclipse 对我说“你不能!在 Employee 中这个方法不存在!”如果你是对的,我尝试编译,它必须有效!因为在运行时在 Employee 变量 (m) 中,我有 Manager.aMethodOfManagerClass() 所以它必须工作,但不是。它没有
        猜你喜欢
        • 2011-03-03
        • 2015-06-02
        • 1970-01-01
        • 1970-01-01
        • 2018-02-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-30
        相关资源
        最近更新 更多