说,有以下示例:
class Super {
public int i = 3;
public void m(Object o) {
System.out.println("Object " + i);
}
public void m(String o) {
System.out.println("String " + i);
}
}
public class Sub extends Super {
public Sub() {
i = 5;
}
public static void main(String[] args) {
Super s = new Sub();
Object o = "";
s.m(o);
s.m("");
}
}
此代码的结果是:
Object 5
String 5
但我认为会是:
String 5
String 5
不要引用set String作为此对象的类型?肯定有一些在引用的帮助下转换为String的情况,所以我对这个基本的例子有点困惑。提前谢谢。
答案 0 :(得分:3)
方法的类型在编译时确定,而不是在运行时确定。 dynamic dispatch仅存在于“参数”this
中 - 对static typing种语言(如java)中的参数没有动态调度。
编译器“选择”应该调用哪个方法,并且由于o
的类型为Object
- 它选择m(Object)
- 它无法知道动态类型{ {1}}实际上是o
。
如果您有兴趣 - 在某些情况下克服此问题的常用方法是使用visitor design pattern。
在您的具体情况下,为了“强制”激活String
,您应该使用m(String)
答案 1 :(得分:2)
在sb.m(o)
中,您使用Object引用调用m(),因此Java会选择该重载。 Java不会选择比传递它的引用类型更具体的重载。它会继续上传继承链。假设你没有m(String o),调用sb.m("Hello")
仍然是合法的,但它会调用对象版本。
如果你要做sb.m((String) o)
,你会得到预期的行为。
答案 2 :(得分:1)
您将对象声明为Object
,因此其类型为Object
。 Java中的类型是强大且静态的,因此当您将对象声明为类型Type
时,它的类型将是终身类型。
如果您希望它是一个字符串,则必须使用toString
方法或强制转换(String)o
答案 3 :(得分:0)
您正在将字符串向下转换为对象。你在做什么与此类似。
public class Sub extends Super {
public Sub() {
i = 5;
}
public static void main(String[] args) {
Super s = new Sub();
Object o = "";
System.out.println("Object Type = " + o.getClass().getName());
s.m(o);
s.m((Object)"");
}
}