我不明白为什么这在java中有效:
如果我在对象中有一个Integer对象,例如:
Object myIntObj = new Integer(5);
如果我这样做:
System.out.println(myIntObj);
输出为:5
我现在认为Integer类有一个toString方法的ovveride,但在这种情况下是不同的(我认为)。 对于多态性,如果我在“父变量”中有一个“子对象”,则该对象不会更改其实际类型(在本例中为Integer)但是......它(在Object变量中)只能使用方法对象类,为什么我写:
System.out.println(myIntObj);
我可以直接看到数字5,而不是这个对象的引用?因为默认情况下,对象类中的toString方法只返回对象引用的字符串。
像:
Object currentPlayer = new Player();
System.out.println(currentPlayer);
在这种情况下,输出是Player objecet的引用,因为在对象类中称为toString方法。
那么为什么在之前的例子中我没有看到引用而是直接看到数字? 通过逻辑,多态的规则说:如果你在“父”变量中有一个“子”对象,那么这个对象在里面,remanis相同,但是他被用作对象的一个对象,所以他可以只使用class对象,所以只是对象的方法,所以真的很奇怪,我没有看到引用而是直接的数字。
我希望你理解我的意思。
答案 0 :(得分:3)
通过将其定义为Object
,这意味着您只能访问Object
类中定义的方法。
这包括toString()
。
因此,当您实例化new Player()
时,您仍然只能访问Object
中的方法,但如果您覆盖此方法(如Integer.toString()
那样),您仍然会按照定义的方式输出在实例化的类中。
PS:父亲 - >父
答案 1 :(得分:3)
您解释推理的最后一段略有不正确。
所以为什么在之前的例子中我没有直接看到引用 数字?通过逻辑,多态的规则说:如果你 在“父”变量中有一个“子”对象,这个对象在里面, 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。
回到你的例子,Integer是一个整数。
Object i = new Integer(5);
i.toString(); // 5
这打印5因为我是一个整数。 Integer类覆盖toString。引用类型(您指向对象的类型)仅确定您可以调用哪些方法,但不能确定调用该方法的哪个父/子类的版本。
答案 2 :(得分:2)
这就是覆盖方法的概念的工作原理:一旦继承层次结构中的某个对象提供了一个实现,就会调用此实现,除非它被继承层次结构中的另一个类覆盖。 / p>
由于java.lang.Integer
提供了toString()
的覆盖,因此会调用此覆盖,而不是java.lang.Object
提供的实现。
System.out.println(myIntObj)
和System.out.println(myIntObj.toString())
之间没有区别,因为println
会在内部调用toString
所有不知道如何打印的对象。
Player
类的行为不同的原因是它不会覆盖toString()
。如果有,你会看到它的结果打印出来。但是,如果没有覆盖,则会调用java.lang.Object
提供的默认实现,它会打印一些通用对象信息。
答案 3 :(得分:1)
Object myIntObj = new Integer(5);
在这里,您要创建一个新的Integer
实例,而不是一个裸Object
实例。您将其分配给Object
引用的事实不会将其转换为裸Object
。它仍然是Integer
,但您可以将其引用为Object
,因为它会扩展Object
。因此,当您致电myIntObj.toString()
时,您正在调用该实例的toString()
方法。该实例结果是Integer
实例。所以Integer.toString()
被称为。{/ p>
Object currentPlayer = new Player();
在这种情况下,调用currentPlayer.toString()
时适用相同的规则:您实际上正在调用Player.toString()
。如果Player
类未覆盖toString()
,则调用第一个升序父类toString()
实现。如果Player
直接延伸Object
,则会调用Object.toString()
,但如果例如Player extends Human
和Human extends Object
,则会调用Human.toString()
如果它存在如果没有,那么Object.toString()
。
答案 4 :(得分:0)
考虑这种情况,其中Employee有一个子类Manager,它有一个方法getDetails()被覆盖,
Employee e=new Employee();
Employee m=new Manager();
如果您调用e.getDetails(),您将获得与Employee相关联的行为。
如果您调用m.getDetails(),您将获得与Manager相关联的行为。
通常,您将获得与变量在运行时引用的对象关联的行为。此行为通常称为虚方法调用。
因此,当您的引用是对象时,您获得与Integer关联的行为的原因是因为您在运行时引用了Integer对象。