在[#0x0009]里面说过,“除了static方法和final方法(final包含private)外,Java对其他所有的方法都采用dynamic binding”(P151, Chapter 8, Thinking in Java, Fourth Edition),不过下面的这个例子也许会让人有点吃惊(adapted from Chapter 8, Thinking in Java, Fourth Edition):
//@file RTTI.java
//RTTI: Run-Time Type Identification
class Useful
{
public void f() {System.out.println("Useful.f()");}
}
class MoreUseful extends Useful
{
public void f() {System.out.println("MoreUseful.f()");}
public void g() {System.out.println("MoreUseful.g()");}
}
public class RTTI
{
public static void main(String[] args)
{
Useful x = new MoreUseful();
x.f();
//x.g();//编译错误:找不到符号
((MoreUseful)x).g(); // Downcast/RTTI
}
}
//output:
/*
MoreUseful.f()
MoreUseful.g()
*/
按理来说,x.f()通过动态绑定能够正确调用MoreUseful的f()方法,那么为什么x.g()就不行呢?真的是“除了static方法和final方法(final包含private)外,Java对其他‘所有’的方法都采用dynamic binding”吗?还是只对覆写方法才动态绑定?
其实这里涉及到动态绑定的细节问题。当然,的确是“除了static方法和final方法(final包含private)外,Java对其他所有的方法都采用dynamic binding”,只不过在使用动态绑定之前,编译器还做了一些其他的工作,而这些工作,就是造成上面代码结果的原因。
Java的方法调用过程:
->编译器查看引用(x)的声明类型(Useful)和方法名(g());
-->通过声明类型找到方法列表;
---->如果方法名不在方法列表中,则编译器报错(g()不在Useful的方法列表里,所以出错);
---->如果方法名在方法列表中,则继续下列步骤;
->编译器查看方法的参数列表,获取参数方法签名;
-->如果方法是private、static、final或者构造器,编译器就可以确定调用那个方法(这是静态绑定);
-->如果不是上述情况,就要使用动态绑定;
可见,x.g()出错是由于使用动态绑定前的方法名检查未通过。从这个角度来说,动态绑定似乎的确只适用于覆写方法。
由于无法使用动态绑定,所以要正确调用x.g()方法,向下转型((MoreUseful)x)就必不可少了。这里x必须指向一个实际的MoreUseful对象(即是通过向上转型得来),如果Useful x = new Useful(),那么((MoreUseful)x)会编译报错。
分享到:
相关推荐
域的定义如果交换环还额外满足以下条件,则称为域:乘法单位元和加法单位元不相等(1不等于0)。由于存在乘法逆元,就意味着可以进行“除法”,所以有的书上也把域称作
0X2B循环for前置知识0X29再谈循环正文Lua除了while和repeat语句还提供了一种for循环语句.while和repeat语句循环终止条件可以是任
0X0E中学算术前置知识0X0D数学库函数正文有了三角函数、反三角函数、对数函数、求幂运算,中学阶段涉及的所有具体的数值计算基本就都可以求解。求此表达式的值:第
目录图例Stage1 入门Stage2 基础Stage3 字符串处理Stage4 理解函数Stage5 表结构Stage6 流程控制Stage7 模块Stage
安全运营相关文章本篇整理一些安全运营相关的高质量文章[2] 体系化的WAF安全运营实践, 安全研究与实践,
1. 度量脚本执行时间 2. 记录时间 3. 计算时间间隔
NULL 博文链接:https://aoyi.iteye.com/blog/659179
NULL 博文链接:https://aoyi.iteye.com/blog/631929
NULL 博文链接:https://aoyi.iteye.com/blog/723571
#define enter 0x1c0d #define A 0x1e61 #define S 0x1f73 #define D 0x2064 #define W 0x1177 #define space 0x3920 #define Y 0x1579 #define n 0x316e int gamespeed=5000; int i,j,key; struct Sor { int x; ...
解决:Windows 10系统连接共享打印机报错0x00000709、0x0000007c、0x0000011b
STM8S207中断系统##pragma 0x原因.pdf,介绍中断的
/*向下翻页移键*/ #define PAGEDOWN 0x5100 /*Escape键*/ #define ESC 0x011b /*左移键*/ #define LEFT 0x4b00 /*右移键*/ #define RIGHT 0x4d00 /*下移键*/ #define DOWN 0x5000 /*上移键*/ #define UP 0x4800 /...
qq不能使用,出现0x0000000C,网页不能打开
#7 0x00002b9405e3c6d0 in __libc_message () from /lib64/libc.so.6 #8 0x00002b9405e4177e in malloc_printerr () from /lib64/libc.so.6 #9 0x00002b9405e42dfc in free () from /lib64/libc.so.6 #10 0x...
非常基本关于C语言的问题,一个信息类(计算机,资讯工程,电子工程, 通信工程)专业的本科毕业生应该达到的水平。题目不难,全部都能快速地答完,当然也需要一定的知识储备。 对于大多数人,我们预期你可能答错 3) 4) 15)...
五子棋源代码,里面有原码和OBJ目标码 #include #define N 20 /*定义键盘*/ #define up 0x4800 #define down 0x5000 #define left 0x4b00 #define right 0x4d00 ... 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
运行QQ提示initialization failure0x0000000c解决方法
#define ENTER 0x1c0d #define DEL 0x5300 #define BACKSPACE 0x0e08 /* 定义F1 到F12 */ #define F1 0x3b00 #define F2 0x3c00 #define F3 0x3d00 #define F4 0x3e00 /* 定义控制键 */ #define...
让您彻彻底底搞清楚回车符(0x0d)与换行符(0x0a)的区别!