问题与记忆和主要表现有关。 最近几天我反思这个话题,这不是我需要使用的东西,只是好奇。 我创建了一个简单的例子:
1)一个不使用委托且没有内部类的类:
public class NoInnerClass {
public void theMethod(int times){
for(int i=0; i<times; i++){
System.out.println("No Inner hello: " + i);
}
}
}
2)一个调用四个内部类的类。最后一个与theMethod方法中的NoInnerClass相同
public class InnerMain {
private Inner1 inner1 = new Inner1();
public void theMethod(int times){
inner1.doIt(times);
}
}
...
public class Inner4 {
public void theMethod(int times){
for(int i=0; i<times; i++){
System.out.println("Inner 4 hello: " + i);
}
}
}
我测量了这两种类型的调用之间的时间差(以毫秒为单位)。 差异并不大 - 超过一毫秒。但是,如果我们有更复杂的内部对象和更多的委托调用,我们肯定会有更大的差异。
所以问题是:
提前感谢您的回答。
答案 0 :(得分:5)
您发现的差异(超过一毫秒)可能是您的基准测试技术的神器。而且,在不知道整个运行时间的情况下谈论毫秒是没有意义的:如果时间是几百毫秒,则差异很小;如果时间本身是一位数毫秒,那么差异很大;如果时间以秒为单位,那么差异就是测量误差。
现代JVM优化了对这种效率水平的虚拟调用,您可以看到的任何差异都很难衡量。使用您可用的所有编码技术(包括虚拟调用)专注于使代码尽可能清晰,并且只有在您的探查器告诉您有必要时才开始优化,这样做要好得多。
答案 1 :(得分:2)
绝大多数计划的差异可以忽略不计。是的,方法调用可能需要几十个cpu周期,但对于大多数方法,这远远小于调用的方法。在您的情况下,您正在进行I / O.即使它只是一个控制台,重新绘制该控制台也比调用方法要昂贵得多。
此外,JVM非常擅长内联方法调用,这进一步减少了方法调用开销(仅对可覆盖的方法进行类型检查)。
我建议您在代码中出现实际性能问题的证据之前不要担心语言结构的性能。
PS:4个方法调用的毫秒数不合理。它可能是您的基准测试方法的工件。 (计时器的准确度如何?你确定基准线程没有被剥离给CPU给另一个程序吗?你是否正在暂停垃圾收集?是否及时运行了编译器?)
哦,关于内存:不同之处在于堆上有4个对象。当然,这取决于这些对象是什么(如果每个引用一个巨大的数组,它可能很重要),但小对象需要16字节的内存。当然你可以节省4 * 16 = 64字节的内存?或者你在询问增加的堆栈大小?这也是微不足道的。