Java-final关键字

---恢复内容开始---

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的值则是不同的。

原文地址:https://www.cnblogs.com/zpoor/p/7600173.html