---恢复内容开始---
final关键字是Java中一个比较重要的关键字,今天我们就来看看他的用法。
一、final关键字的基本用法
在Java中,final关键字可以用来修饰类方法和变量(包括成员变量和局部变量)。下面我们分贝从三方面看一下final关键字的基本用法。
1、修饰类
当用final修饰一个类的时候,表明这个类不能被继承。也就是说,如果一个类永远不让他被继承,就可以用final来修饰。
其中final类中的成员变量可以根据需要设为final,但是final类中的所有成员方法都会隐式设为final方法。
1 package cn.zpoor.test; 2 3 public final class Main { 4 public Main(){ 5 6 } 7 } 8 9 //报错 10 class Test extends Main {//The type Test cannot subclass the final class Main 11 12 }
在使用final修饰类的时候,要注意谨慎选择,除非确定在设计类的时候,这个类不会用来继承。但是出于安全考虑,最好不要将类设计为final类
2、修饰方法
使用final方法的原因:第一个原因是把方法锁定,以防止任何继承类修改它的含义。
第二个原因是效率。在早期Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可以看不到内嵌
调用带来的任何性能提升。在最近java版本中,不需要使用final方法进行这些优化了。因此,如果只有在想明确禁止该方法的
子类中被覆盖的情况下才将方法设置为final。
注意:类的private方法会隐式的被指定为final方法
3、修饰变量
如果修饰的是基本类型变量,则数值一旦初始化之后就不能改变。
如果修饰的是引用类型的变量,则在初始化之后不能让其指向另一个对象。
举个栗子:
1 public class Main { 2 private final int i = 0; 3 4 public Main() { 5 i = 1;//报错 The final field Main.i cannot be assigned 6 final Object obj = new Object(); 7 obj = new Object();//报错 8 //The final local variable obj cannot be assigned. 9 //It must be blank and not using a compound assignment 10 } 11 }
二、深入理解final关键字
1、类的final变量和普通变量有什么区别?
当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要在使用初始化之前被赋值即可)
必须在定义时或者在构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后就不能被改变。
举个栗子:
1 public class Main { 2 public static void main(String[] args) { 3 String a = "zpoor2"; 4 final String b = "zpoor"; 5 String d = "zpoor"; 6 String c = b + 2; 7 String e = d + 2; 8 9 System.out.println((a == c)); 10 System.out.println((a == e)); 11 } 12 } 13 14 /*结果是: 15 true 16 false*/
结果分析:
当final变量是基本类型以及String类型,如果编译期间能够直到确切值,则编译器就会吧他当成编译器常量使用。相当于直接使用这个常量,其他变量则要链接才能使用。需要注意的是只有直到确切final值,编译器才会这样的优化,下面这段代码不会进行优化。
1 public class Main { 2 public static void main(String[] args) { 3 String a = "zpoorlove"; 4 final String b = getHello();//final的值不是确切的 5 String c = b + "love"; 6 System.out.println((a == c)); 7 } 8 9 public static String getHello() { 10 return "Hello"; 11 } 12 } 13 14 /*结果是: 15 false*/
2、被final修饰的引用变量只想的对象内容可变吗?
举个栗子:
1 public class Main { 2 public static void main(String[] args) { 3 final Test test = new Test(); 4 System.out.println(++test.i); 5 } 6 7 } 8 9 class Test { 10 public int i = 0; 11 } 12 13 /*结果是: 14 1 15 */
顺利通过,说明引用变量被final修饰之后,最然不能指向其他对象,但是它指向的对象的内容是可以改变的。
3、final 和 static (我经常搞混淆)
static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。
1 public class Main { 2 public static void main(String[] args) { 3 Test test1 = new Test(); 4 Test test2 = new Test(); 5 6 System.out.println(test1.i); 7 System.out.println(test1.j); 8 System.out.println(test2.i); 9 System.out.println(test2.j); 10 } 11 12 } 13 14 class Test { 15 public final int i = (int)(Math.random()*10); 16 public static int j = (int)(Math.random()*10); 17 } 18 19 /*结果是: 20 21 */
可以看出:每次打印的两个j的只都是一样的,而i的值则是不同的。