final可以修饰变量(各种变量)、方法、类。
final与abstract互斥:永远不能同时出现
一、final修饰变量
final修饰变量:该变量被附初始值之后不能被重新赋值。
final修饰的变量必须被赋值,且只能赋值一次。
1、final修饰成员变量
非final的成员变量,程序员可以不显示指定初始值,系统会为之分配默认初始值。
final的成员变量,程序员必须指定初始值。
-
final实例变量,必须显式指定初始值。
只能在一下3个位置其中之一指定:
–定义时指定初始
–实例初始化块
–每个构造器。
以上2个位置的本质其实只有一个:构造器。 -
final类变量,必须显式指定初始值。
只能在一下2个位置其中之一指定:
–定义时指定初始值
–类初始化块
以上2个位置的本质其实只有一个:类初始化块。
2、final修饰局部变量
非final的局部变量,程序员必须指定初始值,然后才能使用。
final的局部变量,程序员必须指定初始值,然后才能使用。final的局部变量不能被重新赋值。
3、final修饰引用类型的变量
final只能保证该引用变量本身不会被重新赋值,该变量所引用的变量完全可以被修改。
public class FinalTest
{
public static void main(String[] args)
{
final Pig p = new Pig("白色",34.4);
//final只能保证p不能被重新赋值
//p = new Pig("黑色",44.5);
//程序完全可以修改final变量所引用的对象
p.setColor("黑色");
p.setWeight(44.5);
}
}
4、final修饰“宏替换”的变量
- 如果一个变量满足以下3个条件:
–变量有final修饰
–声明变量时指定了初始值
–变量的初始值可以在编译时确定下来(初始值的表达式没有变量、方法调用)
这个变量就会消失,所有出现该变量的地方,在编译时就会替换成该变量的值。
public class FinalTest
{
public static void main(String[] args)
{
String st1 = "aa"; //第一次用字符串,该字符串进入缓冲池
String st2 = "aa"; //第二次直接用缓冲池中的字符串
System.out.println(st1 == st2); //true
String st3 = "aabb"; //第一次用字符串,该字符串进入缓冲池
String st4 = "aa" + "bb"; //编译阶段就会计算结果:aabb
System.out.println(st3 == st4); //true
String st5 = "aa";
String st6 = "bb";
String str = st5 + st6; //st5、st6是变量,要等运行时才能计算结果
System.out.println(st3 == str); //false
final String st7 = "aa";
final String st8 = "bb";
String str1 = st7 + st8; //st5、st6会消失,相当于String str = "aa" + "bb";
System.out.println(st3 == str1); //true
}
}
二、final修饰方法
表明该方法不允许被子类重写-----该方法可以被重载,也可以被子类调用。
- 【备注】private方法已经被隐藏在该类的内部,子类无法访问该方法,因此不可能被重写。final修饰private方法纯属多余,但Java是允许的。
三、final修饰类
表明该类不能派生子类。
JDK里很多类都是final:String、Math、System ······