本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42497857
在上一篇文章中介绍了“分解临时变值“。本文将介绍“移除对参数的赋值”这种重构手法。
下面让我们来学习这种重构手法吧。
发现:代码对一个参数进行赋值。
解决:以一个临时变量取代该参数的位置。
	//重构前
	int dicount(int inputVal, int quantity, int yearToDate){
		if(inputVal > 50) inputVal-=10;
	}	//重构后
	int dicount(final int inputVal, int quantity, int yearToDate){
		int result = inputVal;
		if(result > 50) result-=10;
	}动机
我想你很清楚“对参数赋值”这个说话的意思。如果把一个名称为fool的对象作为参数传递给某个函数,那么“对参数赋值”意味改变fool,使它引用另一个对象。但是,如果在“被传入对象”身上进行什么操作,那没问题,我们经常会这么做。这里只针对“fool被改变而指向另一个对象”这种情况来讨论:
void test(Object fool){
	fool.changedBySomeWay(); //that's ok
	fool=anotherObject; //trouble will appear
}        我们之所不这样做,是因为它降低了代码的清晰度,而且混用了按值传递和按引用传递这两种参数传递方式。JAVA只采用按值进行传递。
在按值传递的情况下,对参数的任何修改,都不会对调用端造成任何影响。如果你只以参数表示“被传递进来的东西”,那么代码会清晰的多,因为这种用法在所有语言中都表现出相同的语义。
        在JAVA中,一般不要对参数赋值:如果你看到手上的代码已经这么做了,就应该使用本文的方法。
	int dicount(int inputVal, int quantity, int yearToDate){
		if(inputVal > 50) inputVal-=5;
		if(quantity > 100) quantity-=10;
		if(yearToDate > 1000) yearToDate-=100;
		return inputVal;
	}        以临时变量取代对参数的赋值动作,得到下列代码:	int dicount(int inputVal, int quantity, int yearToDate){
		int result  = inputVal;
		if(result > 50) result-=5;
		if(quantity > 100) quantity-=10;
		if(yearToDate > 1000) yearToDate-=100;
		return result;
	}        可以为参数加上final关键词,强制其遵循“不对参数赋值”这一惯例:	int dicount(final int inputVal, final int quantity, final int yearToDate){
		int result  = inputVal;
		if(result > 50) result-=5;
		if(quantity > 100) quantity-=10;
		if(yearToDate > 1000) yearToDate-=100;
		return result;
	}
我们应该都知道,JAVA使用按值传递的函数调用方式,这常常也会使大家迷惑。在所有地点,JAVA都会遵循严格按值传递:
	//JAVA按值的传递
	class Params{
		public static void main(String[] args) {
			int x = 10;
			triple(x);
			System.err.println("x after triple:" + x);
		}
		
		private static void triple(int arg){
			arg = arg * 3;
			System.err.println("arg in triple:" +arg );
		}
	}
	//输出
	//arg in triple:30 
	//x after triple:10//以对象为参数
class Params{
	public static void main(String[] args) {
		Date d1 = new Date(2015,1,1);
		nextDateUpdate(d1);
		System.err.println("d1 after nextday:" + d1);
		
		Date d2 = new Date(2015,1,1);
		nextDateReplace(d2);
		System.err.println("d2 after nextday:" + d2);//61380864000000
		
	}
	private static void nextDateUpdate(Date d) {
		d.setDate(d.getDate()+1);
		System.err.println("arg in nextday d1 : "+d);
	}
	private static void nextDateReplace(Date d) {
		d = new Date(d.getYear(),d.getMonth(),d.getDate()+1);
		d=null;
		System.err.println("arg in nextday d2: "+d);
	}
}
//输出
/*
 arg in nextday d1 : Tue Feb 02 00:00:00 CST 3915
 d1 after nextday:   Tue Feb 02 00:00:00 CST 3915
 arg in nextday d2:  Tue Feb 02 00:00:00 CST 3915
 d2 after nextday:   Mon Feb 01 00:00:00 CST 3915
 */        从本质上说,对象的引用是按值传递的。因为可以修改参数对象的内部状态,但对参数对象重新赋值是没有意义的。        本文主要介绍了重构手法——移除对参数的赋值。我觉得这个重构手法使用的情况并不常见,一般情况下,我们都觉得没有必要把参数的值重新定义。但是为了让代码显得比较清晰,在某些情况下还是值得做的。
        最后,希望本文对你有所帮助。有问题可以留言,谢谢。(PS:下一篇将介绍重构笔记——以函数对象取代函数)
原文:http://blog.csdn.net/pistolove/article/details/42497857