非常本质的问题,极难,代码增加了注释很好看懂,对JVM没有兴趣就不用进来看了

mfCVinci 2004-11-02 05:19:56
import java.util.*;

class OrgClass
{
//只所以是空函数是为了减少其它时间的影响,你可以在里面加上一些语句看看
void funEmpty(){}
};

class MidClass extends OrgClass
{
void funEmpty(){}
};

class EndClass extends MidClass
{
//main中调用的funEmpty应该都是这个函数
void funEmpty(){}
};

class MyFunCall
{
public static void main(String[] args)
{
/*objEnd,objOrg,objMid指向同一个EndClass类型的对象
(我们称呼它THEOBJ),我们知道其实这三个变量的本质是引用*/
EndClass objEnd = new EndClass();
OrgClass objOrg = (OrgClass)objEnd;
MidClass objMid = (MidClass)objEnd;

//为了说明问题,设置了一个循环,以尽量消除其它线程的影响
for(int outCyc = 0;outCyc<10;outCyc++)
{
//使用objOrg来调用THEOBJ的方法,并计算调用10000000次的时间
long begin1 = System.currentTimeMillis();
for(long i = 0;i<10000000;i++)
objOrg.funEmpty();
long end1 = System.currentTimeMillis();
System.out.println("From objOrg,timespan is:" + (end1-begin1));

//使用objMid来调用同样的方法,同样是10000000次
long begin2 = System.currentTimeMillis();
for(long i = 0;i<10000000;i++)
objMid.funEmpty();
long end2 = System.currentTimeMillis();
System.out.println("From objMid,timespan is:" + (end2-begin2));

//使用objEnd来调用同样的方法,同样是10000000次
long begin3 = System.currentTimeMillis();
for(long i = 0;i<10000000;i++)
objEnd.funEmpty();
long end3 = System.currentTimeMillis();
System.out.println("From objEnd,timespan is:" + (end3-begin3));

System.out.println("");
}
}
}
...全文
150 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
Banned 2005-03-19
  • 打赏
  • 举报
回复
可能的办法:查看编译后的字节码即可知道答案
DeadWolf 2004-11-04
  • 打赏
  • 举报
回复
没注意到 100000000 比你代码多了一个0吧 :)

你的结果也是注释掉后的结果啊
{//引用
注释掉 MidClass和EndClass后我运行结果为
From objOrg,timespan is:120
From objMid,timespan is:60
From objEnd,timespan is:61
objMid和objEnd的运行时间可以认为相等。
}

以下是没有注释掉的结果
objEnd最短,objMid,objOrg几乎没有差别,和你的结果也有出入
是不是引用本身是EndClass ,不需要额外处理工作的缘故

From objOrg,timespan is:2253
From objMid,timespan is:2374
From objEnd,timespan is:1522

From objOrg,timespan is:2173
From objMid,timespan is:2133
From objEnd,timespan is:1362

From objOrg,timespan is:2263
From objMid,timespan is:2234
From objEnd,timespan is:1412

From objOrg,timespan is:2203
From objMid,timespan is:2423
From objEnd,timespan is:1853

From objOrg,timespan is:2403
From objMid,timespan is:2504
From objEnd,timespan is:1332

From objOrg,timespan is:2073
From objMid,timespan is:2383
From objEnd,timespan is:1482

From objOrg,timespan is:2134
From objMid,timespan is:2163
From objEnd,timespan is:1582

From objOrg,timespan is:2073
From objMid,timespan is:2253
From objEnd,timespan is:1432

From objOrg,timespan is:2223
From objMid,timespan is:2133
From objEnd,timespan is:1423

From objOrg,timespan is:2313
From objMid,timespan is:2233
From objEnd,timespan is:1342





mfCVinci 2004-11-04
  • 打赏
  • 举报
回复
你把 MidClass 和 EndClass 的funEmpty都注释掉了结果当然一样。
保留MidClass 去掉 EndClass的 看看。

另:你的机器真够慢的啊
DeadWolf 2004-11-03
  • 打赏
  • 举报
回复
From objOrg,timespan is:1803
From objMid,timespan is:1772
From objEnd,timespan is:1713

From objOrg,timespan is:1752
From objMid,timespan is:1783
From objEnd,timespan is:1832

From objOrg,timespan is:1963
From objMid,timespan is:1853
From objEnd,timespan is:1732

From objOrg,timespan is:1783
From objMid,timespan is:1682
From objEnd,timespan is:1753

From objOrg,timespan is:1812
From objMid,timespan is:1763
From objEnd,timespan is:1763

From objOrg,timespan is:1712
From objMid,timespan is:1823
From objEnd,timespan is:1662

From objOrg,timespan is:1692
From objMid,timespan is:1813
From objEnd,timespan is:1803

From objOrg,timespan is:1612
From objMid,timespan is:1762
From objEnd,timespan is:1713

From objOrg,timespan is:1803
From objMid,timespan is:1702
From objEnd,timespan is:1783

From objOrg,timespan is:1782
From objMid,timespan is:2223
From objEnd,timespan is:1923


按你的程序运行,看不出什么差别!
上面是我100000000次循环的 10 轮结果,几乎没有什么差别!!!
这是注释掉以后的结果。

用的是最新的JDK1.42,因为我不是学Java的,今天在Sun网站上下的
mfCVinci 2004-11-02
  • 打赏
  • 举报
回复
to DeadWolf(三角小眼睛又邪又媚又笨又呆又奸又诈又色)

想知道他们到底执行了那一个只要往各自的方法里面填充点东西就知道了。
mfCVinci 2004-11-02
  • 打赏
  • 举报
回复
注释掉 MidClass和EndClass后我运行结果为
From objOrg,timespan is:120
From objMid,timespan is:60
From objEnd,timespan is:61
objMid和objEnd的运行时间可以认为相等。


我的结论是:

比如有类A,B,C;B从A继承,C从B继承。A有方法X,B改写了X,但C未改写X。
现在有A,B,C的对象a,b,c,分别用他们来调用X。对于b和c,java可以知道它们调用的都是B的方法X,可以直接编译为函数调用。而对于a来说,它调用的可能是A的X或B的X,所以必须通过虚函数表来调用。时间的差别就是直接调用和通过虚函数表调用的差别。

说明java对动态关联的东西进行了优化,以提高程序运行的效率。
DeadWolf 2004-11-02
  • 打赏
  • 举报
回复
不是很了解Java

不过已我的感觉
应该不象你在
class EndClass extends MidClass
{
//main中调用的funEmpty应该都是这个函数
void funEmpty(){}
};
注释中写的
三个循环都是执行的统一个函数

我觉得三个循环应该分别执行的是各自的funEmpty
执行时间应该差不多

如果把MidClass 和 EndClass 的funEmpty方法注释掉,那么三个循环到是执行的同一个,即OrgClass的funEmpty,但是执行时间EndClass > MidClass >OrgClass

希楼主给出测试结果,不知道如我所猜
classjava 2004-11-02
  • 打赏
  • 举报
回复
????
mfCVinci 2004-11-02
  • 打赏
  • 举报
回复
然后请把 MidClass 和 EndClass 的funEmpty方法注释掉后编译重新运行,并观察结果发表高论。谢谢。
mfCVinci 2004-11-02
  • 打赏
  • 举报
回复
有兴趣的编译执行,观察后发表看法。谢谢。

50,523

社区成员

发帖
与我相关
我的任务
社区描述
Java相关技术讨论
javaspring bootspring cloud 技术论坛(原bbs)
社区管理员
  • Java相关社区
  • 小虚竹
  • 谙忆
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧