有时在算法的过程中,我们需要计算或简单地存储几个相互依赖或彼此分开没有任何意义的值。
就像一个(非常荒谬,但重要的是,简单)示例让我们在 anint[]
中找到最接近 number的两个不同值3
:
int a = values[0];
int b = values[1];
for (int value : values) {
int distance = Math.abs(value-3);
if (value != b) {
if (distance < Math.abs(a-3) ) {
a = value;
}
}
if (value != a) {
if (distance < Math.abs(b-3) ) {
b = value;
}
}
}
takeSausageSliceBetween(a, b);
我们不能只在同一个类中创建方法computeA()
,computeB()
因为计算a
和b
是相互依赖的。所以计算a
并且b
只是要求重构为一个单独的类:
class DistinctNumbersNearestTo3 {
final int a;
final int b;
DistinctNumbersNearestTo3(int[] values) {
// same algorithm
}
}
因此更高级别的代码变得清晰明了:
DistinctNumbersNearestTo3 nearest = new DistinctNumbersNearestTo3(values);
takeSausageSliceBetween(nearest.a, nearest.b);
// nearest never leaves the method it was declared in
但是(如果我错了,请纠正我)它引入了,至少对于某些级别的优化,一个实例化,然后是一个新对象的垃圾收集(只是来自伊甸园,但无论如何)只是为了清楚你的代码。并且在堆栈中寻找 int 也会变成在堆中寻找对象。
这里的问题是: JVM 是否足够聪明,最终可以优化重构的代码以像未重构的代码一样运行?
我想将几个变量组合成一个新对象只是为了更清晰的代码的另一种情况是,当我想a()
通过引入一个新类来将一个长方法重构为几个新方法时,该类C
包含特定于a()
's 调用的数据,因此包含那些对这些数据进行操作的几种新方法。我在实现一个表示一组链的类时偶然发现了这种情况,我们可以向其中添加新的链接(节点对),从而扩展现有的链,将两条链组合在一起,或者创建一个包含两个节点的新链。让我们仅出于某种观点讨论该特定类:
public class SetOfChains {
List<List<Node>> chains;
public void addLink(Node a, Node b) {
// Very long method that mutates field this.chains. Needs refactoring.
}
}
要正确拆分addLink
为 的几个方法SetOfChains
,这些新方法中的每一个都必须有很多参数,因为addLink()
在addLink()
. 将该数据保存到的专用字段SetOfChains
也是可能的,但有异味且难以表达(因为它仅在方法调用期间才有意义),因此显然我创建了一个新的内部类来将该数据保存在其字段中并执行所有算法步骤,chains
像未重构的那样改变外部字段addLink()
:
class SetOfChains{
List<List<Node>> chains;
void addLink(Node a, Node b) {
new LinkAddition(a,b).compute();
}
class LinkAddiditon { // Instances never leave addLink()'s scope
private final Something bunch, of, common, fields;
compute() {
this.properly();
this.isolated();
this.steps();
this.of();
this.the();
this.refactored();
this.method();
}
// There be code for the properly isolated steps...
}
但是由于在功能上这相当于让我的旧 long unrefactored addLink()
,JVM 是否可以使生成的指令与未重构情况下一样优化,就好像没有任何LinkAddition
对象一样?
因此,要在这堵文字墙下画出底线:如果我通过将数据和方法提取到新类而不是方法来争取易于理解的代码,是否必然会导致性能下降?
我是否正确理解所描述的案例正是逃逸分析的内容?