java方法调用有多贵

jhl*_*u87 76 java methods performance call

我是初学者,我一直都认为重复代码是不好的.但是,似乎为了不这样做,通常需要额外的方法调用.假设我有以下课程

public class BinarySearchTree<E extends Comparable<E>>{
    private BinaryTree<E> root;
    private final BinaryTree<E> EMPTY = new BinaryTree<E>();
    private int count;
    private Comparator<E> ordering;

    public BinarySearchTree(Comparator<E> order){
        ordering = order;
        clear();
    }

    public void clear(){
        root = EMPTY;
        count = 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

将clear()方法中的两行复制并粘贴到构造函数中而不是调用实际方法,对我来说是否更为理想?如果是这样,它会产生多大的差异?如果我的构造函数进行了10次方法调用,每次调用只是将一个实例变量设置为一个值,该怎么办 什么是最好的编程实践?

Vin*_*lds 70

将clear()方法中的两行复制并粘贴到构造函数中而不是调用实际方法,对我来说是否更为理想?

编译器可以执行该优化.JVM也是如此.编译器编写者和JVM作者使用的术语是"内联扩展".

如果是这样,它会产生多大的差异?

测量它.通常,你会发现它没有任何区别.如果你认为这是一个性能热点,那你就是在错误的地方; 这就是你需要测量它的原因.

如果我的构造函数进行了10次方法调用,每次调用只是将一个实例变量设置为一个值,该怎么办

同样,这取决于生成的字节码和Java虚拟机执行的任何运行时优化.如果编译器/ JVM可以内联方法调用,它将执行优化以避免在运行时创建新堆栈帧的开销.

什么是最好的编程实践?

避免过早优化.最佳实践是编写可读且设计良好的代码,然后针对应用程序中的性能热点进行优化.

  • @jhlu87:我认为你很难准确估计方法调用的开销.微观标记是很难做到的,即使这样,在宏观方案中通常也不是很有用.阅读[this](http://code.google.com/p/caliper/wiki/JavaMicrobenchmarks). (2认同)

Dan*_*tin 18

其他人对优化所说的话绝对是真的.

从性能的角度来看,没有理由内联该方法.如果这是性能问题,JVM中的JIT将内联它.在java中,方法调用非常接近自由,因此不值得考虑它.

话虽如此,这里有一个不同的问题.即,它不好的编程习惯调用一个方法覆写投放(即,一个是不final,staticprivate从构造器).(Effective Java,2nd Ed.,p.89,标题为"继承的设计和文档或禁止它"的项目)

如果有人添加了一个BinarySearchTree被调用的子类LoggingBinarySearchTree,会使用以下代码覆盖所有公共方法,会发生什么?

public void clear(){
  this.callLog.addCall("clear");
  super.clear();
}
Run Code Online (Sandbox Code Playgroud)

LoggingBinarySearchTree将永远不会构建!问题是,this.callLognull在当BinarySearchTree构造函数运行,但clear被调用是重写一个,你会得到一个NullPointerException.

请注意,Java和C++在这里有所不同:在C++中,调用virtual方法的超类构造函数最终会调用超类中定义的那个,而不是被覆盖的类.在两种语言之间切换的人有时会忘记这一点.

鉴于此,我认为在构造函数中调用clear方法内联方法可能更简洁,但通常在Java中,您应该继续进行所需的所有方法调用.

  • 他明确地问道"什么是最好的编程实践?" - 作为最佳实践,这是完全相关的. (3认同)
  • 我不认为他是在要求编码风格技巧,而是想知道方法调用是否昂贵 (2认同)
  • 如果你只拿最后一句话,你就完全失去了这个问题的背景.他想知道将大方法分解成许多较小的方法是否很昂贵,因为方法调用需要付出代价.添加描述用于从构造函数调用非最终方法的反模式的答案并不算作整体问题的答案.哦,看看问题的标题"方法调用有多贵" (2认同)

Mar*_*elo 5

我肯定会保持原样.如果你改变了clear()逻辑怎么办?找到复制2行代码的所有地方是不切实际的.