final 关键字
final:代表最终的、不可变的
常用的四种方法:
1、可以用来修饰一个类
2、可以用来修饰一个方法
3、可以用来修饰一个局部变量
4、可以用来修饰一个成员变量
一、修饰一个类
当一个类被 final 修饰时,这个类不能有任何子类(断子绝孙)
格式:
public final class 类名称 {
// ......
}
注意:如果一个类是 final 的,那么其中所有的成员方法都无法进行覆盖重写(因为没有儿子)
public final class Fu {
}
// Zi 类继承 Fu ,出现报错
public class Zi extends Fu {
}
常见的 final 类:String类
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
// .....
}
注意
: 在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类
二、修饰一个方法
当 final 关键字用来修饰一个方法的时候,这个方法就是最终方法,不能被覆盖重写。但是这个方法任然可以被继承
格式:
修饰符 final 返回类型 方法名称(参数列表) {
// 方法体
}
public class Fu {
public final void function(){
System.out.println("刘雨昕");
}
}
public class Zi extends Fu {
// 报错,子类不可以覆盖父类的 final 方法
public final void function(){
}
}
public class Fu {
public final void function(){
System.out.println("刘雨昕");
}
}
public class Zi extends Fu {
public static void main(String[] args) {
Zi zi = new Zi();
// 父类的 final 方法,子类任然可以调用
Zi.functuon();// 刘雨昕
}
}
注意
:
1、对于类、方法来说, abstract关键字和final关键字不能同时使用。
2、 如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。
三、修饰一个局部变量
一旦使用final用来修饰局部变量,那么这个变量就不能进行更改。
“—次赋值,终生不变“
final int num = 100;
num = 200;// 错误
num = 100;// 错误
final int num;
num = 100;// 正确!!!只要保证有唯一一次赋值即可
对于基本类型来说,不可变说的是变量当中的
数据
不可改变对于引用类型来说,不可变说的是变量当中的
地址值
不可改变
final Student s = new Studnet("刘雨昕");
// s = new Studnet("刘妞妞");// 错误
System.out.println(s.getName());// 刘雨昕
s.setName("刘妞妞");
System.out.println(s.getName());// 刘妞妞
四、修饰一个成员变量
对于成员变量,如果使用 final 修饰的时候,那么这个变量也是不可变的
1、成员变量具有默认值,所以用了 final 之后鼻祖手动赋值,不会再给默认值了
public class Student {
private final String name;// 错误
}
2、对于 final 的成员变量,要么使用直接赋值,要么通过构造方法赋值。(二选一)
3、必须保证类中所有的重载的构造方法,都最终会对 final 的成员变量进行赋值
五、final 关键字的好处
1、 final关键字提高了性能。JVM 和 Java 应用都会缓存final变量。
2、 final变量可以安全的在多线程环境下进行共享,而不需要额外的同步开销。
3、 使用final关键字,JVM 会对方法、变量及类进行优化。
六、常见面试题
讲讲 final 和 finally 和 finalize() 的区别?
final:可以修饰类、方法、局部变量、成员变量
前面已经讲过了
finally: java的一种异常处理机制
finally是对Java异常处理模型的最佳补充。finally结构使代码总会执行,而不管有无异常发生。使用finally可以维护对象的内部状态,并可以清理非内存资源。特别是在关闭数据库连接这方面,如果程序员把数据库连接的close()方法放到finally中,就会大大降低程序出错的几率。
public static String m() {
try {
int a = 10;
return "try-return";
}finally {
System.out.println("finally");
return "finally-return ";
}
}
public static void main(String[] args) {
System.out.println(m());
}
打印结果:
finally
finally-return
为什么还会打印finally呢?
首先finally语句在改代码中一定会执行,从运行结果来看,仿佛其他return语句被屏蔽掉了。
事实也确实如此,因为finally用法特殊,所以会撤销之前的return语句,继续执行最后的finally块中的代码。
finalize():Java中的一个方法名。
finalize()是在 java.lang.Object
里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。 使用finalize还需要注意一个事,调用super.finalize();
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。
七、总结
-
final关键字可以用于成员变量、本地变量、方法以及类。
-
final类不能被继承
-
final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
-
不能够对final变量再次赋值
-
在匿名类中所有变量都必须是final变量
-
子父类之间final方法不能被重写
-
final关键字不同于finally关键字,后者用于异常处理
-
final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法
-
接口中声明的所有变量本身是final的
-
final和abstract这两个关键字是反相关的,final类就不可能是abstract的
-
没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”
-
将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化
-
按照Java代码惯例,final变量就是常量,而且通常常量名要大写