um9237
2009-09-02 16:04
浏览 292
已采纳

java的多态会极大影响速度吗?

给出以下代码和运行结果,盼各位指点。。。。。。

对于接口A,抽象类B,一般类C,各自只有一个共同的方法,通过get()方法返回一个值

设计另外三个类:AA实现接口A,BB继承抽象类B,CC继承一般类C

设计test()方法,初始化三个类后,执行各个对象中的get()方法1000000000次,在形如B b = new BB()的前提下,通过b.get()样式运行后时间消耗远远大于通过((BB)b).get()循环的时间消耗,其他几个类似,代码附下

哪位能给出个比较详细的解释吗?

[code="java"]package cn.edu.uestc.dmlab.clusterers.dbscan;

public class InheritancePerformanceTest {
interface A {
public int get();
}

abstract class B {
    public abstract int get();
}

class C {
    public int get() {return 2;}

}

class AA implements A {
    @Override
    public int get() {return 1;}
}

class BB extends B {
    @Override
    public int get() {return 1;}
}

class CC extends C {
    @Override
    public int get() {return 1;}
}

public void test() {
    A a = new AA();
    B b = new BB();
    C c = new CC();
    int s = 1000000000; 
    long t =System.currentTimeMillis();

    System.out.println("--start--");

    for (int i = 0; i < s; i++) {
        get();
    }
    System.out.println("this: \t" + (System.currentTimeMillis()-t));


    System.out.println("\n- polymorphism -----------");

    t =System.currentTimeMillis();;
    for (int i = 0; i < s; i++) {
        a.get();
    }
    System.out.println("implements interface: \t"+(System.currentTimeMillis()-t));

    t = System.currentTimeMillis();
    for (int i = 0; i < s; i++) {
        b.get();
    }
    System.out.println("extends abstract:     \t"+ (System.currentTimeMillis()-t));

    t = System.currentTimeMillis();
    for (int i = 0; i < s; i++) {
        c.get();
    }
    System.out.println("extends class:        \t"+ (System.currentTimeMillis()-t));



    System.out.println("\n-no polymorphism -----------");

    t = System.currentTimeMillis();
    for (int i = 0; i < s; i++) {
        ((AA)a).get();
    }
    System.out.println("implements interface: \t"+ (System.currentTimeMillis()-t));

    t = System.currentTimeMillis();
    for (int i = 0; i < s; i++) {
        ((BB)b).get();
    }
    System.out.println("extends abstract:     \t"+ (System.currentTimeMillis()-t));

    t = System.currentTimeMillis();
    for (int i = 0; i < s; i++) {
        ((CC)c).get();
    }
    System.out.println("extends class:        \t"+ (System.currentTimeMillis()-t));

    System.out.println("\n--end--");
}

public int get() {
    return 1;
}

public static void main(String[] args) {
    InheritancePerformanceTest a = new InheritancePerformanceTest();
    a.test();
}

}
[/code]
[b]问题补充:[/b]
to jansel:
调换过了也一样,由于结果不在一个数量级,所以先后顺序并不会影响多少。谢谢回答。
[b]问题补充:[/b]
另外,这里并不是突发奇想来测试这个,确实是在编写一个算法的时候感觉到了时间消耗的巨大差军,才专门做这个试验以求根本性解释问题,指导试验,请各位指点。谢谢!
[b]问题补充:[/b]

to qqxiaodi:
请问需要加什么样的“清理语句”呢?谢谢!

to lovewhzlq:
不好意思,我没从那些文章里看出关于这段代码问题的所以然来,麻烦你能不能解释下我的测试为什么有问题呢?谢谢!

[b]问题补充:[/b]

另外,整个实验就在于使用b.get()方法和((BB)b).get()方法的区别,代码顺序可以随便变换,也可以分成两个来测试

由于使用b.get()时间消耗和使用((BB)b).get()差距在5倍以上,所以我觉得跟机器的关系不大,由代码来看,跟垃圾收集也应该没多大关系。

[b]问题补充:[/b]
to walsh:
很奇怪你的测试结果,我当然不会随便测试一下就拿上来请教大家,而是分别在10多台机子上测试了这个程序,无论机子配置好坏,得到的结果都是类似如下的结果(比例类似,绝对值不同)
[quote]--start--
this: 1812

  • polymorphism ----------- implements interface: 1782 extends abstract: 8859 extends class: 8578

-no polymorphism -----------
implements interface: 1328
extends abstract: 1344
extends class: 1313

--end--[/quote]

另外,就算你这里关于B的结果不能说明问题,那C的又如何解释呢,甚至A的也不符合你的说法呢?
[b]问题补充:[/b]
to walsh:
不好意思,我没有不相信你的意思,但是我又在8台不同机子上做了同样的测试,整个实验过程近20台机子的测试结果仍然和我上述的结果差不多,我真的不能重复你的实验结果。

整个过程中我最关心的只是b.get()方法和((BB)b).get(),c.get()方法消耗时间多一些可以理解,我不理解的只是b.get()这个抽象方法在继承以后为什么会和c.get()类似。既然你不能重复我的实验结果,而我也不能重复你的实验结果,这个。。。。。难道还有什么其他的问题导致的这个问题啊???看来我还需要继续等待以及测试一下。
  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

10条回答 默认 最新

  • walsh_bupt 2009-09-03 10:58
    已采纳

    --start--
    this: 2875

    • polymorphism ----------- implements interface: 3625 extends abstract: 1578 extends class: 6313

    -no polymorphism -----------
    implements interface: 2859
    extends abstract: 2828
    extends class: 2891

    --end--

    这个是我公司机子运行的效果,具体原因,我上面已经解释的很清楚了

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • iteye_15225 2009-09-02 16:08

    LZ把后面的测试代码调到前面再测试一下。

    在一个方法中测试这些很不准的,LZ忽略了CPU和内存,以及回收了

    评论
    解决 无用
    打赏 举报
  • iteye_15225 2009-09-02 16:21

    如果是算法的话,本身也很少会用到多态,都是一块代码就搞完了。

    忽然想到Lucene的代码里面多态很少的原因是不是也考虑到这个问题了

    评论
    解决 无用
    打赏 举报
  • QQxiaodi 2009-09-02 16:45

    在开发的过程中确实很少用到像LZ现在用的东东,建议加上一些清理语句 然后再测试下看看效果。

    评论
    解决 无用
    打赏 举报
  • wanghaolovezlq 2009-09-02 16:48

    你的测试本身就是有问题的

    看看一些文章

    http://lovewhzlq.iteye.com/category/76246

    评论
    解决 无用
    打赏 举报
  • walsh_bupt 2009-09-02 20:11

    [size=medium] 由于使用b.get()时间消耗和使用((BB)b).get()差距在5倍以上????[/size]

    楼主,你这句话很值得怀疑呀。

    在我机子上测试结果如下:
    [quote]--start--
    this: 3000

    • polymorphism ----------- implements interface: 3485 extends abstract: b.get() 1875 extends class: 8469

    -no polymorphism -----------
    implements interface: 2109
    extends abstract: ((BB) b).get() 2109
    extends class: 2125

    --end--[/quote]

    明显是((BB)b).get()消耗的时间大于b.get()。

    其实原因很简单:多的时间就在于强制类型转换。

    评论
    解决 无用
    打赏 举报
  • walsh_bupt 2009-09-02 20:15

    [size=medium]多态有多态存在的好处,这个是肯定的。再说了,楼主,你做的这个测试好像和多态没有关系吧,你测试的只是方法的调用,如果你要是明白方法是如何被调用的,已经继承时候被调用的顺序,估计就会明白了。[/size]

    评论
    解决 无用
    打赏 举报
  • walsh_bupt 2009-09-03 10:49

    楼主上面的测试结果是我在机子上跑了很多次,并且每次几乎都是一样的,只是差别很小,对于你说的,

    对于 a.get(); 运行时间大于((AA)a).get(); 的运行时间,其实也是很简单的:
    因为接口其实编译之后就是抽象类,在运行的时候,遇到遇到a.get()首先会试图调用抽象类中的get()方法,因为该方法是abstract,继而转到继承类中调用相应的get()方法,这个过程很花费时间的(注意java中采用的是后期绑定),

    而对于((AA)a).get(); 已经明确指定了是调用AA中的get()方法,所以只是只是先做类型转换,然后直接调用AA中的get()方法。

    楼主,你应该看到了.((AA)a).get(); 和 ((BB) b).get();花费的时间是相当的。

    而对于c.get();花费的时间远远大于 ((CC)c).get(); 道理也很简单。
    后者只是做类型转化花费点时间,而对于前者,首先需要判断是调用父类中的get()方法还是调用子类中的get()方法,这个是很花费时间的,所以前者远远大于后者运行的时间。

    楼主,建议你去看看,深入理解虚拟机这本书吧 。

    对于我的运行结果,你也没有必要怀疑,我们做开发的,说是就是,说不是就是不是。

    评论
    解决 无用
    打赏 举报
  • walsh_bupt 2009-09-03 11:07

    楼主,你也可以通过点击下边的链接,看我在Eclipse中的运行结果图:

    [url]http://dl.iteye.com/upload/attachment/142255/ee99f561-9f7f-3de4-9c82-1dddc73a2d55.png[/url]

    评论
    解决 无用
    打赏 举报
  • pmachine 2009-09-04 22:55

    我的测试结果
    环境:
    windows 7 (已激活)
    MyEclipse 6.6
    JDK 1.5
    CPU:Intel E2140

    --start--
    this: 4168

    • polymorphism ----------- implements interface: 4709 extends abstract: 2519 extends class: 11522

    -no polymorphism -----------
    implements interface: 2864
    extends abstract: 2859
    extends class: 2871

    --end--

    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题