过时的Java优化技巧
过时的Java优化技巧
在Java中,对方法和方法参数使用final修饰符对性能没有任何帮助。在Java HotSpot wiki中,可以了解到HotSpot使用的优化技巧以及如何在Java代码中有效地使用它们。然而,这个链接似乎并没有排除final。它表示'final'是内联的一个提示。我认为即使在循环中调用其他方法并超出当前范围,final修饰符也可以确保编译器知道其值不会改变。在stackoverflow.com上有相关讨论。在方法(或类)上使用final对JIT提供的信息没有影响。然而,在方法参数上使用final可能会提供有用的优化提示(类似于声明为final的局部变量)。但是,使用final的原因是强制不可变性-这是一种设计时的特性,可以使代码更容易维护。任何优化效果都需要考虑两个问题:a)只有在实际存在性能问题时才需要担心,b)需要彻底测试以确保它真的有所改变。
实际上,对参数使用final通常不会有任何影响(编译器确实可以看到您是否对其进行赋值,但Java不会通过引用传递变量-对象通过引用传递,但持有它们的变量不会)。但是,它确实意味着参数可以与内部类或匿名类一起使用。如果有意义的话可以使用,否则不要使用。
我使用final来确保类的不可变性,通常是作为私有final字段。我还使用它来确保不更改传递参数的值/引用。换句话说,我只是为了正确性而使用它,而不是为了优化。
我不使用final在方法参数或方法变量上进行优化,我使用它作为编码实践,以便其他开发人员可以看到这个值确实不会改变。任何优化都是次要的。
问题的出现的原因:
问题的出现是因为在早期开发阶段进行性能优化是不必要的,而且可能会导致额外的复杂性和困扰。因此,需要在开始性能优化之前明确定义时间/内存的权衡。
解决方法:
1. 不要在开发的早期阶段进行性能优化,除非真正需要。如果决定进行性能优化,可以采取以下步骤:
2. 使用性能分析工具查找瓶颈,并检查源代码以找到瓶颈的原因;
3. 选择适当的数据结构,以最好地适应已定义的时间/内存权衡;
4. 选择适当的算法(例如迭代与递归等);
5. 避免使用Java库中的同步对象,除非真正需要;
6. 避免显式/隐式创建新对象;
7. 如果确定Java自带的数据类型/算法不符合要求,可以进行重写/重新实现;
8. 使用小型、独立的测试来测试选择的算法/数据结构的性能。
此外,为了减轻第一条规则的影响,有一些易于编写和阅读的方法,任何合格的软件工程师都应该知道并正确地做到,比如在链表和数组列表之间进行选择。这是免费的,并且可以避免以后的麻烦。这就是良好的软件设计的本质。
过时的Java优化技巧
在Java编程中,有些人会将字符串连接操作String a = "this" + var1 + " is " + var2;
替换为多次调用StringBuilder或StringBuffer。实际上,Java编译器已经在幕后使用了StringBuilder。
在这种情况下,我认为优化仍然适用。你展示的示例代码将构建3个不同的StringBuilder实例,每个连接操作都会构建一个实例;而只构建一个实例会更高效(稍微)。如果我错了,请纠正我。
哦,我以为它会等同于String a = new StringBuilder("this").append(var1).append("is").append(var2).toString();
?
这个不可靠的来源rgagnon.com/javadetails/java-0129.html表明Paul是正确的,只使用一个StringBuilder,但它说StringBuilder的默认容量可能太短(奇怪的是,如果编译器在使用StringBuffer之前计算容量是微不足道的)。
使用StringBuffer甚至会降低代码的速度,因为它涉及同步操作。在一个过度使用StringBuffer的应用程序中,我将所有出现的StringBuffer替换为StringBuilder,性能提高了10%。
当字符串连接操作在一行上完成时,使用StringBuilder没有任何作用。然而,将这个:String a = "this" + var1; a += " is " + var2;
替换为StringBuilder仍然有效。(至少在我上次检查时是有效的:-)
我认为你是对的,因为将其拆分成多行将涉及创建大量不同的String对象。
在最后一天,“谁在乎这是否被优化?”(考虑到绝大多数使用场景。)
stackoverflow.com/questions/22241841/…是一个例子,将循环中的+=
替换为单个StringBuilder
显著影响了性能;在该例中,执行时间从35分钟减少到6分钟。
如果你在循环中进行了成千上万次的字符串连接操作,这确实是一种值得优化的方法,但是我回答中的示例不会节省你可测量的时间。