double temp = 2 * (_height + _widgth);
System.out.println(temp);
temp = _height * _widgth;
System.out.println(temp);
==〉
final double perimeter = 2 * (_height + _widgth);
System.out.println(perimeter);
final double area = _height * _widgth;
System.out.println(area);
动机:
临时变量有各种不同用途,其中某些用途会很自然地导致临时变量被多次赋值。[循环变量]和[集用临时变量]就是两个典型例子:循环变量(loop variable)会随循环的每次运行而改变(例如for(int i=0; i <10;i++)语句中的i);集用临时变量(collection temporary variable)负责将[通过整个函数的运算]而构成的某个值收集起来。
除了这两种情况,还有很多临时变量用于保存一段冗长代码的运算结果,以便稍后使用。这种临时变量应该只被赋值一次。如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果临时变量承担多个责任,它就应该被替换(剖解)为多个临时变量,每个变量只承担一个责任。同一个临时变量承担两件不同的事情,会令代码阅读者糊涂。
作法:
1 在[待剖解]之临时变量的声明式及其第一次被赋值处,修改其名称。
如果稍后之赋值语句是[i = i + 某表达式]形式,就意味这是个集用临时变量,那么就不要剖解它。集用临时变量的作用通常是累加、字符串接合、写入stream或者向群集(collection)添加元素。
2 将新的临时变量声明为final。
3 以该临时变量之第二次赋值动作为界,修改此前对该临时变量的所有引用点,让它们引用新的临时变量。
4 在第二次赋值处,重新声明原先那个临时变量。
5 编译,测试。
6 逐次重复上述过程。每次都在声明处对临时变量易名,并修改下次赋值之前的引用点。
double getDistanceTravelled(int time) {
double result;
double acc = _primaryForce / _mass;
int primaryTime = Math.min(time, _delay);
result = 0.5 * acc * primaryTime * primaryTime;
int secondaryTime = time - _delay;
if(secondaryTime > 0) {
double primaryVel = acc * _delay;
acc = (_primaryForce + _secondaryForce) / _mass;
result += primaryvel * secondaryTime + 0.5 * acc * secondaryTime * secondaryTime;
}
return result;
}
acc变量有两个责任:第一是保存第一个力造成的初始加速度;第二是保存两个力共同造成的加速度。这就是我想要剖解的东西。
首先,我在函数开始处修改这个临时变量的名称,并将新的临时变量声明为final。接下来我把第二次赋值之前对acc变量的所有引用点,全部改用新的临时变量。最后,我在第二次赋值处重新声明acc变量:
double getDistanceTravelled(int time) {
double result;
final double primaryAcc = _primaryForce / _mass;
int primaryTime = Math.min(time, _delay);
result = 0.5 * primaryAcc * primaryTime * primaryTime;
int secondaryTime = time - _delay;
if(secondaryTime > 0) {
double primaryVel = primaryAcc * _delay;
double acc = (_primaryForce + _secondaryForce) / _mass;
result += primaryvel * secondaryTime + 0.5 * acc * secondaryTime * secondaryTime;
}
return result;
}
新的临时变量的名称指出,它只承担原先acc变量的第一责任。我将它声明为final,确保它只被赋值一次。然后,我在原先acc变量第二次被赋值处重新声明acc。现在,重新编译并测试,一切都应该没有问题。
然后,我继续处理acc临时变量的第二次赋值。这次我把原先的临时变量完全删掉,代之以一个新的临时变量。新变量的名称指出,它只承担原先acc变量的第二个责任:
double getDistanceTravelled(int time) {
double result;
final double primaryAcc = _primaryForce / _mass;
int primaryTime = Math.min(time, _delay);
result = 0.5 * primaryAcc * primaryTime * primaryTime;
int secondaryTime = time - _delay;
if(secondaryTime > 0) {
double primaryVel = primaryAcc * _delay;
final double secondaryAcc = (_primaryForce + _secondaryForce) / _mass;
result += primaryvel * secondaryTime + 0.5 * secondaryAcc * secondaryTime * secondaryTime;
}
return result;
}
以下是我自己对以上的代码进行的重构,未测试,仅供参考。
double getDistanceTravelled(int time) {
GetDistance(time) + GetSecondDistance(time);
}
double GetDistance(int time)
{
return 0.5 * GetPrimaryAcc()* GetPrimaryTime(time)* GetPrimaryTime(time);
}
double GetSecondDistance(int time)
{
if(GetSecondTime(time)> 0) {
return GetPrimaryAcc()* _delay * GetSecondTime(time)+
0.5 * GetSecondAcc()* GetSecondTime(time)* GetSecondTime(time);
}
else
{
return 0;
}
}
double GetPrimaryAcc()
{
return _primaryForce / _mass;
}
double GetSecondAcc()
{
return (_primaryForce + _secondaryForce) / _mass;
}
double GetPrimaryTime(int time)
{
return Math.min(time, _delay);
}
double GetSecondTime(int time)
{
return time - _delay;
}