今天在看《程序员修炼之道》的时候看到了以”final“来修饰的方法参数,想起了之前在项目中也有人这么写,当然知道final修饰的属性无法被变动的,但是用在参数中,除了无法让其修改参数外,还有什么深意么?处于好奇就google了下。
在《Thinking in Java》中有这么一句:Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法在方法中更改参数引用所指向的对象。
不过是不能改变这个引用,或是不能改变引用所指向的对象,还是二者都不可修改呢?
做个例子,如下:
public int intTest(final int i){
//i++; 错误
//i += 1; 错误
//i = 1; 错误
return i;
}
public String stringBufferTest(final StringBuffer str){
//str = new StringBuffer(); 错误
str.append("a");
return str.toString();
}
注解中标有错误的都无法通过编译,使用IDE话直接提示错误。
通过测试,第二个方法运行正常,所以得出结论,final修饰的参数,引用是绝对不允许修改的,而引用所指向的对象是可以修改的。(网上给出的例子很多,我只是无聊自己试了下)
不过查资料过程中也看到了网友给出的一个疑问的例子
class Value {
int val = 0;
}
public class FinalArgument{
public static void funValue(Value v){
v = new Value();
++v.val;
}
public static void funValueFinal(final Value v){
//!v = new Value();
funValue(v);
}
public static void main(String[] args){
Value a =new Value();
System.out.println( "a.val= " + a.val);
funValueFinal(a);
System.out.println( "a.val= " + a.val);
}
}
代码的输入结果是:
a.val=0
a.val=0
疑问在于,既然final参数不能修改为什么还能传给一个可变的参数,为什么在funValue方法内的改变没法改变外部的值。
第一点,JAVA没有限定不可以把final修饰的常量传给非final的。
public String stringTest(final StringBuffer str){
//str = new StringBuffer(); 错误
str.append("a");
StringBuffer newSB = str;
return newSB.toString();
}
上面代码,完全合法。
而关于第二个疑问,完全JAVA的一个基本知识的理解不够透彻的结果,或则说是对JAVA参数传递的理解不够深入。JAVA的实参实际是一个副本,即在作为参数传入时候把原来的变量拷贝一份进入栈中,也就是说,原有的变量和参数实际是两个不同的...不知道怎么说了,用C语言来说就是两个不同的指针,但是指针所指向的地址是同一个,这就是为什么对传入的参数的引用内容做修改会影响到方法外面的变量。但是当new一个新的时候,参数的指向的地址发生了变化,所以...
可以参考下以下文章,就会有个深入的理解,文章来自“梦想风暴”的博客——《Java基本功——reference》