面向对象通识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);
}
}
/*
true
true
false
true
*/
例题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 {
@Override
public 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
在这里是多余的。