面向对象通识16(final修饰符)
final可以修饰变量(各种变量)、方法、类
final与abstract是互斥的,无法同时出现。
特性
final修饰类变量
- 该变量被赋初始值之后,不能被重新赋值。
- 该变量必须被赋值
final修饰成员变量
- 对于普通的成员变量,可以不显示指定的初始值,系统会位置分配默认的初始值。
(该初始值分配规则与数组元素的初始值分配规则完全相同)
对于
final修饰的成员变量,程序员必须分配指定的初始值final实例变量,必须显示指定的初始值。只能在以下3个位置的其中之一指定:定义时指定初始值
实例初始化块
构造器
上面三个位置本质上都是要还原到构造器
不能在普通方法中赋值!public class Final实例变量 {final int age=20;final String s="java";;final long lg;{lg=2333333;}public void sc(){}}
final修饰的类变量,必须显示指定的初始值。只能在以下2个位置的其中之一指定:定义时指定初始值
类初始化快
本质上都是在类初始化快中指定初始值
实例初始化快可以访问final类变量,但不能指定初始值public class Final类变量 {static final int a=10;static final String m;static {m="z";}void a(){System.out.println(m);}}
对于非
final修饰的局部变量,程序员必须指定初始值,然后才能使用对于
final修饰的局部变量,程序员必须指定初始值,然后才能使用,与前者唯一的区别就是不能被重新赋值如果
final修饰的是引用类型的变量——final只能保证该引用变量本身不会被重新赋值,该变量所引用的对象完全可以被修改
public class Final引用类型 {public static void main(String[] args) {final Pig p=new Pig("white",4);//只能保证p不能被重新赋值p.setColor("black");p.setWeight(5);System.out.println(p.getColor());System.out.println(p.getWeight());}}class Pig{private String color;private int weight;public Pig(String white, int i) {}public void setColor(String color){this.color=color;}public void setWeight(int weight){this.weight=weight;}public String getColor(){return this.color;}public int getWeight(){return this.weight;}}
final修饰宏替换的变量
条件
- 变量有
final修饰 - 声明变量时指定初始值
- 变量的初始值可以在编译的时候确定下来(初始值的表达式中没有变量、方法调用等)
这个变量就会消失,所有出现该变量的地方,在编译的时候就会出现该变量的值
public class 宏变量 {public static void main(String[] args) {final int MAX=100;//有final修饰,指定了初始值,并且初始值在编译的时候就可以确定}}
举例:
public class 宏变量 {public static void main(String[] args) {String a="a";String b="a";System.out.println(a==b);String s1="accd";String s2="ac"+"cd";//编译阶段就会计算结果System.out.println(s1==s2);String s3="ac";String s4="cd";String c=s3+s4;//s3和s4是变量,在运行的时候才会计算System.out.println(c==s1);final String s7="ac";final String s8="cd";String d=s7+s8;//s7和s8有final修饰并在声明的时候已经指定了初始值,出现了宏替换System.out.println(d==s1);}}/*truetruefalsetrue*/
例题2
public class 例题 {public static void main(String[] args) {final String s1="wyd";final String s2=s1+" is";final String s3=s2+" unjuanable";System.out.println(s3);}}/*wyd is unjuanable*/
上述代码经过了3次宏替换
final修饰方法
被final修饰的方法可以被重载,可以被子类调用,但不能被重写(避免该方法被子类破坏)
举例1
class A{public final void info(){System.out.println("info");}}public class 调用方法 extends A {@Overridepublic void info(){System.out.println("change");}}/*'info()' cannot override 'info()' in 'Final宏变量.A'; overridden method is final*/
举例2
class Foo {//private方法已经隐藏在该类的内部不可能被重写,子类无法访问private final void test(){System.out.println("2333");}}public class F1 extends Foo{public void test(){System.out.println("32222");}public static void main(String[] args) {F1 a=new F1();a.test();}}/*32222*/
在例2中 private方法已经隐藏在该类的内部不可能被重写,子类无法访问,
逻辑上final在这里是多余的。
