Java——静态和动态;动态类型--”;这印的是什么;
所以我在理解这个类中展示的示例时遇到了一些困难——它应该说明Java中静态和动态类型之间的微妙之处Java——静态和动态;动态类型--”;这印的是什么;,java,oop,inheritance,dynamic,static,Java,Oop,Inheritance,Dynamic,Static,所以我在理解这个类中展示的示例时遇到了一些困难——它应该说明Java中静态和动态类型之间的微妙之处 public class Piece { public static void main (String[] args) { Piece p2 = new Knight(); Knight p1 = new Knight(); p1.capture(p2); // call 1; "Knight is bored" is supposed
public class Piece {
public static void main (String[] args) {
Piece p2 = new Knight();
Knight p1 = new Knight();
p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
}
public void capture () {
System.out.println("Capturing");
}
public void capture (Piece p) {
System.out.println("I'm bored")
}
public class Knight extends Piece {
public void capture (Piece p) {
System.out.println("Knight is bored");
}
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY");
}
}
以下是我对这两个电话的理解:
呼叫1:p1.捕获(p2)
捕获方法从p1调用。通过动态类型查找,可以看到p1的动态类型是Knight。所以它看起来是在Knight子类中。p2作为参数传入。为了查看在Knight子类中调用哪个捕获方法,它检查p2的静态类型,这是一个片段。因此,印刷了“骑士无聊”。这是正确的输出,但我的推理正确吗
呼叫2:p2.捕获(p1)
使用相同的推理,从p2调用捕获方法。通过动态类型查找,可以看到p2的动态类型是Knight。所以它看起来是在Knight子类中。p1作为参数传入。要查看要调用哪个捕获方法,它将查看p1的静态类型,即Knight。因此,打印“太慢的伙伴”。显然,我的推理是错误的,因为这不是真正的印刷品。有什么方向吗
谢谢 我记得,我已经学会了“扩展”的意思是“将新的放在旧的上面,但不删除它”,如果您要“覆盖”该方法,它就像您描述的那样。
在您的情况下,如果调用“p1.capture(p1)”,应该会导致“太慢了,伙计”(但我没有尝试)。我不认为此示例告诉您静态类型和动态类型之间的区别。您甚至不需要考虑超类和子类。它只是告诉您方法定义。-->只有当调用方、方法名称、参数名称和参数类型都相同时,才会调用正确的方法。在第二次调用中,只能调用Piece类的方法或其子类中的相同方法。这就是为什么它将调用捕获(p件)而不是捕获(骑士k件)。后者是骑士阶级特有的
例如,当我们有“List a=new Arraylist();”时,您只能调用在List中声明的方法,而不能调用Arraylist中外观相似的附加方法。当您将
@Override
注释添加到Knight
的方法时,它变得清晰起来
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY");
}
此方法未被重写-它是新的,添加到Knight
类中
因此,它只能用于类型为Knight
的对象,例如:Knight k=newknight()代码>
您没有这样的示例,即在Knight
上以Knight
作为参数调用此方法。您在带片骑士和带片骑士上调用了capture
p1.capture(p2); // call 1; "Knight is bored" is supposed to be printed
p2.capture(p1); // call 2; "knight is bored" is supposed to be printed
p1.capture(p1); // call 3: TOO SLOW BUDDY <- look here :)
p1.捕获(p2);//呼叫1;“骑士无聊”应该是印刷出来的
p2.捕捉(p1);//呼叫2;“骑士无聊”应该是印刷出来的
p1.捕捉(p1);//呼叫3:太慢了,伙计
在这里,您正在对工件类对象调用捕获方法,因为您已经传递了p1(Knight)类引用,所以它将调用Knight类的重写捕获方法。就是
public void capture (Piece p) {
System.out.println("Knight is bored");
}
如果运行以下代码-
public class Piece {
public static void main (String[] args) {
Piece p2 = new Knight();
Knight p1 = new Knight();
p1.capture(p2);
p2.capture(p1);
}
public void capture () {
System.out.println("Capturing");
}
public void capture (Piece p) {
System.out.println("I'm bored");
}
}
}
结果是——
我很无聊
我很无聊
因此,动态查找检查子类是否重写了函数 是的,p1。捕捉(p1)会导致“太慢的伙伴”;然而,我感到困惑的是另外两个案例,而不是这个案例;)嗯。因为p2的静态类型是一个片段,所以它只知道捕获(片段p)方法,而不知道捕获(骑士k)方法?那么,它是如何进入Knight子类并获取该方法的版本的呢?抱歉,还是有点困惑。那是因为骑士扩展了一块,p2是骑士对象。这意味着您只能调用Piece方法,但如果Knight有一个具有相同签名的方法,它将调用该方法。您的意思是p2是Piece类型的对象吗?@RyanYu:是的,与我的示例中的a
在其余代码中是列表的方式相同。但是当在a
上调用方法时,它被认为是ArrayList
@RyanYu:我认为p2是类型Piece的引用和类型Knight的对象。。希望它能回答你…好的,谢谢。当你说“它只能用于Knight类型的对象”时,你指的是它们的静态类型,对吗?换句话说,骑士n;将属于knight类型。@Ryan Yu,您有两种类型-引用类型和动态对象对象:type staticTypeOfReference=new dynamicpolimorficObjects that canextendtypedeclared()代码>:)好的,让我看看我是否有这个权利,最后:对于p1.capture(p2),它看到p1的类型是Knight&p2的类型是Piece,所以它在Knight子类中检查一个捕获方法,该方法将Piece作为参数。它发现了这一点,并打印出“骑士很无聊”,此外,对于p2.capture(p1),它看到p2是类型片,p1是大小骑士。它查看正在从中调用捕获的类(p2--Piece),发现没有接受Knight类型参数的方法。但是有一个方法接受Piece类型的参数!然后,动态查找告诉该方法在子类(Knight)中签入一个方法,该方法覆盖它找到的这个捕获方法。然后,它使用这个覆盖方法打印“Knight is bored”。@Ryan Yu-此外,对于p2.capture(p1),它看到p2是类型Piece
-这里p2的类型无关紧要,它被直接解析为Knight,静态解析发生在您将对象传递给某个方法时-然后检查静态类型,对其子类的实际引用根本不重要<代码>p2.capcure(p1)
-此调用知道p2是Knight类的对象,引用类型为Piece(但在这里并不重要…),并且它知道p1的引用类型为Knight(调用构造函数的最后一方),即Piece的子类。
public class Piece {
public static void main (String[] args) {
Piece p2 = new Knight();
Knight p1 = new Knight();
p1.capture(p2);
p2.capture(p1);
}
public void capture () {
System.out.println("Capturing");
}
public void capture (Piece p) {
System.out.println("I'm bored");
}
class Knight extends Piece {
// public void capture (Piece p) {
// System.out.println("Knight is bored");
// }
public void capture (Knight k) {
System.out.println("TOO SLOW BUDDY"+k);
}