final在java的作用当然不止是对变量的修饰,在这里简单的介绍一下final在java中的作用。
修饰类:
表明该类不可被继承,类中的所有成员方法都隐式的被指定为final方法,成员变量则可以定义为final,也可以不定义为final;
修饰方法:
用final修饰方法的原因有两个:
- 锁定这个方法,防止任何继承类修改它的含义;
- 提高效率:在方法前面添加final进行修饰可以提高效率,其原理是基于内联/内嵌(inline)机制,它会使你在调用final方法时,直接将方法的主体插入到调用处,从而省去调用函数所花费的开销。但是如果方法过于庞大或者其中有循环的话,这种提高效率的方法可能会失效。
修饰变量:
终于还是到这里了。
在java中,final对变量的修饰的作用,是防止变量值的改变;
- 如果修饰的是基本类型数据变量,则该变量的值不能发生改变;
- 如果修饰的是引用类型数据变量,则该变量不会内二次初始化;
解释:由于引用类型数据变量被初始化后,其值是一个地址,所以不会被二次初始化,则地址不改变。
特别备注:final对引用类型变量的修饰效果:
/**
* 这是一个测试,证明final在修饰引用类型参数的时候能够保证参数不被二次初始化。
*
* 过程:
* 1.定义一个自定义类变量test;
* 2.定义一个String测试变量str;
* 3.定义一个String变量str2,用来测试str的地址是否改变;
* 4.在初始化后进行一次test和str的地址输出;
* 5.在调用函数后再进行一次test和str的地址输出;
* 6.比较两次地址是否发生改变;
*
* 解释:因为test和str都是引用类型变量,所以变量经过初始化后它们的值都是一个地址,
* 因此只有地址没有改变,则可以证明该变量没有被二次初始化。
*
*/
public static void main(String args[]) {
String str = "";
MyTest Test = new FinallyTest().new MyTest();
final String str2 = str;
// 未调用函数前的地址
System.out.println("调用函数前的test地址:" + Test);
// 进行地址比较,因为无法直接获得str的地址,所以通过比较的方式证明str的地址没变。
System.out.println("调用函数前的str地址:" + (str == str2));
// 调用函数进行测试
testClass(Test);
testString(str);
// 调用函数后的地址
System.out.println("调用函数后的test地址:" + Test);
System.out.println("调用函数后的str地址:" + (str == str2));
}
// final修饰MyTest
public static void testClass(final MyTest test) {}
// final修饰String
public static void testString(final String str) {}
public class MyTest {
public void change(final String str) {}
}
运行结果:
内容补充:
类的final变量和普通变量有什么区别?
当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。
引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的。
static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。