1、Java方法形参被final修饰
1)final修饰基本变量
如果修饰的是基本变量,基本类型的值是不能改变的
/**
* 对于基本类型,基本类型的值在方法内部是不能够改变的
* @param i
*/
public static void checkInt(final int i)
{
//编译不通过,final修饰的局部变量i的值是不能够改变的
// i=10;
}
2)final修饰的是引用类型的变量
如果修饰的是引用类型的变量,引用类型变量所指的引用是不能改变的,但引用类型变量的值是可以改变的。
/** * 对于基本类型,基本类型的值在方法内部是不能够改变的 * @param i */
public static void checkInt(final User user) {
//user变量的引用是不能够改变的,否则的话,编译会报错
// user=new User();
//user变量的值是能够修改的,但所指向的引用是不能够改变的
user.setUserName("小王");
}
3)匿名内部类调用形参时,形参需要final
当所在的方法的形参需要被内部类里面使用时,该形参必须为final。
内部类编译成功后,它会产生一个class文件,该class文件与外部类并不是同一个class文件,仅仅只保留对外部类的引用。当外部类传入的参数需要被内部类调用时,从java的角度来看是直接被调用:
public class OuterClass {
public void display(final String name,String age){
class InnerClass{
void display(){
System.out.println(name);
}
}
}
}
从上面代码中看好像name参数应该是被内部类直接调用?其实不是,在java编译之后实际的操作如下:
public class OuterClass$InnerClass {
public InnerClass(String name,String age){
this.InnerClass$name = name;
this.InnerClass$age = age;
}
public void display(){
System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );
}
}
所以从上面代码来看,内部类并不是直接调用方法传递的参数,而是利用自身的构造器对传入的参数进行备份,自己内部方法调用的实际上时自己的属性而不是外部方法传递进来的参数。
直到这里还没有解释为什么是final?在内部类中的属性和外部方法的参数两者从外表上看是同一个东西,但实际上却不是,所以他们两者是可以任意变化的,也就是说在内部类中我对属性的改变并不会影响到外部的形参,而然这从程序员的角度来看这是不可行的,毕竟站在程序的角度来看这两个根本就是同一个,如果内部类该变了,而外部方法的形参却没有改变这是难以理解和不可接受的,所以为了保持参数的一致性,就规定使用final来避免形参的不改变。
简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变。
故如果定义了一个匿名内部类,并且希望它使用一个其外部定义的参数,那么编译器会要求该参数引用是final的。
另外,匿名内部类没有构造器,而一般我们都是利用构造器完成某个实例的初始化工作的,那如何初始化匿名内部类呢?使用构造代码块。
2、方法被修饰final
方法被修饰为final时,子类不能重写父类的final方法,但父类的final方法为private时,子类可以命名和父类一样的方法。
3、String被设置成final的原因
1)线程安全
2)支持字符串常量池数据共享,节省资源,提高效率(因为如果已经存在这个常量池便不会再创建,直接拿来用)