夯实Java基础(九)——final关键字

一、前言

Java语言中的final关键字,想必你们都不是很陌生,咱们本身用的最多的应该是用来定义常量吧,那么今天咱们就来了解final这个关键字的用法,这个关键字仍是很是简单的。html

final从字面意思是不可更改的,最终的意思,它能够用来修饰类、方法、变量(包括成员变量和局部变量)、参数。优化

二、final修饰类

final修饰类,表示该类不能再被继承了,若是一个类它的功能比较完整,不须要扩展功能,咱们就可使用final来修饰。咱们最经常使用String、Integer、System等类就是用final修饰的,其不能再被其余类所继承。this

用final修饰类若是被继承了那么在编译的时候就会报错。spa

三、修饰方法

final修饰方法,表示这个方法不能被子类方法重写。若是你认为一个方法的功能已经足够完整了,不须要再去子类中扩展的话,咱们能够声明此方法为final。好比Object类中getClass()方法就是final修饰的。code

 

注意:类中全部的private方法都自动成为final。因为不能访问一个private方法,因此它绝对不会被覆盖。htm

四、修饰变量

final修饰变量表示是常量,通常都和static一块儿使用,用来定义全局常量。final不管修饰的是成员变量仍是局部变量,都必须进行显式初始化,以下。对象

 1 public class FinalTest {
 2     //显式初始化
 3     final int AA=11;
 4     final int BB;
 5     final int CC;
 6     final int DD;
 7     //构造代码块初始化
 8     {
 9         BB=22;
10     }
11     //构造方法初始化
12     public FinalTest(){
13         CC=33;
14         DD=44;
15     }
16 
17     public FinalTest(int CC, int DD) {
18         this.CC = CC;
19         this.DD = DD;
20     }
21 }

咱们能够经过显式初始化、构造代码块初始化、构造方法初始化这三种方式对final修饰的变量进行初始化。blog

前面都是讲的final修饰基本数据类型的变量,若是final修饰引用变量会是怎么样,咱们来看一下举例:继承

 1 public class FinalTest {
 2 
 3     public static void main(String[] args) {
 4         final AA aa = new AA();
 5         //这里在引用其余的对象就会报错Cannot assign a value to final variable 'aa'
 6         //aa=new AA();
 7         aa.i++;
 8         System.out.println(aa.i);
 9     }
10 
11 }
12 
13 class AA{
14     int i;
15 }
16 
17 //运行结果:1

能够看到,虽然咱们将引用变量用final修饰了,可是该对象的变量 i 咱们仍是能够进行修改,而这个变量的引用不能再指向另外一个对象了。代表final修饰的是引用变量,就不能再指向其余对象,可是若是该对象内的变量不是final修饰的,其变量的值是能够进行修改的。get

五、修饰参数

final修饰参数准确的来讲应该是修饰形参,代表该形参的值不能被修改。

 1 public class FinalTest {
 2 
 3     public static void main(String[] args) {
 4         FinalTest f=new FinalTest();
 5         f.show(5);
 6     }
 7 
 8     public void show(final int param){
 9         //编译报错:Cannot assign a value to final variable 'param'
10         //param=10;
11         System.out.println(param);
12     }
13 }

我在使用final修饰形参时,代表此形参是一个常量。当咱们调用方法的时候,给形参进行赋值,一旦赋值之后,就只能在该方法使用,并且不能进行从新赋值操做,不然编译报错。若是形参是引用类型,则引用变量不能再指向其余对象,可是该对象的内容是能够改变的。

六、类的final变量和普通变量有什么区别?

参考连接:http://www.javashuo.com/article/p-heipsycl-n.html

当用final做用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只须要保证在使用以前被初始化赋值便可)必须在定义时或者构造器中进行初始化赋值,并且final变量一旦被初始化赋值以后,就不能再被赋值了。那么final变量和普通变量到底有何区别呢?下面请看一个例子:

 1 public class Test { 
 2     public static void main(String[] args)  { 
 3         String a = "hello2";   
 4         final String b = "hello"; 
 5         String d = "hello"; 
 6         String c = b + 2;   
 7         String e = d + 2; 
 8         System.out.println((a == c)); 
 9         System.out.println((a == e)); 
10     } 
11 }

输出结果:true、false
     你们能够先想一下这道题的输出结果。为何第一个比较结果为true,而第二个比较结果为fasle。这里面就是final变量和普通变量的区别了,当final变量是基本数据类型以及String类型时,若是在编译期间能知道它的确切值,则编译器会把它当作编译期常量使用。也就是说在用到该final变量的地方,至关于直接访问的这个常量,不须要在运行时肯定。这种和C语言中的宏替换有点像。所以在上面的一段代码中,因为变量b被final修饰,所以会被当作编译器常量,因此在使用到b的地方会直接将变量b 替换为它的值。而对于变量d的访问却须要在运行时经过连接来进行。想必其中的区别你们应该明白了,不过要注意,只有在编译期间能确切知道final变量值的状况下,编译器才会进行这样的优化,好比下面的这段代码就不会进行优化:

 1 public class Test { 
 2     public static void main(String[] args)  { 
 3         String a = "hello2";   
 4         final String b = getHello(); 
 5         String c = b + 2;   
 6         System.out.println((a == c)); 
 7   
 8     } 
 9       
10     public static String getHello() { 
11         return "hello"; 
12     } 
13 }

这段代码的输出结果为false。这里要注意一点就是:不要觉得某些数据是final就能够在编译期知道其值,经过变量b咱们就知道了,在这里是使用getHello()方法对其进行初始化,他要在运行期才能知道其值。

相关文章
相关标签/搜索