Final关键字
基本介绍
final
可以修饰类、属性、方法和局部变量
以下几种情况可能用到final
关键字:
- 不希望类被继承时
- 不希望某个方法被子类覆盖/重写时
- 不希望类的某个属性值被修改
- 不希望某个局部变量被修改
final
也可以用来修饰形参,但是不用final
来修饰构造器
//Final01.java
public class Final01 {
public static void main(String[] args) {
}
}
//以下被注释掉的是错误语法
//不希望被继承
final class A{//不能 class B extends A{}
}
//不希望某个方法被重写
class C{
public final void hi(){
}
/**
*
* class D extends C{
* @Override
* public void hi() {//不能在D中重写
* super.hi();
* }
* }
*/
}
//不希望某个属性值被修改
class E{
public final double TAX_RATE = 0.01;
/**
* 不能在主函数中 修改e的值
* E e = new E();
* e.TAX_RATE = 0.1;
*/
}
//不希望某个局部变量被修改
class F{
public void cry(){
final double NUM = 0.01;//不能 NUM = 1;
}
}
注:属性值要创建对象后修改,局部变量值可以在函数体内修改。
注意事项
-
final
修饰的属性又叫常量,习惯用 全大写字母 + 下划线来 表示 -
final
修饰的属性在定义时必须赋初值,并且以后不可以再修改。赋值可以选择以下任意一个位置:- 定义该变量时
- 在构造器中
- 在代码块中
-
如果final修饰的属性是静态的,则初始化的位置只能是:
- 定义该变量时
- 在静态代码块中
- 不能在构造器中(因为类加载静态变量要先于调用类的构造器)
-
final
类不能继承,但是可以实例化 -
如果不是
final
类但是含有final
方法,则该方法虽然不能重写,但是可以被继承。
//FinalDetail01.java
public class FinalDetail01 {
public static void main(String[] args) {
CC cc = new CC();//可以实例化final修饰的类 CC
new EE().cal();//EE中没有任何代码但可以使用继承的方法
}
}
class AA{
// 给final修饰的变量赋初值
public final double TAX_RATE = 0.1;//1. 定义该变量时
public final double TAX_RATE2;
public final double TAX_RATE3;
public AA(){//2. 在构造器中
TAX_RATE2 = 1.1;
}
{//3. 在代码块中
TAX_RATE3 = 2.2;
}
}
class BB{
//给final修饰的 静态 变量赋初值
public static final double TAX_RATE = 1.1;//1. 定义该变量时
public static final double TAX_RATE2;
static {//2. 在静态代码块中
TAX_RATE2 = 2.2;
}
/** 不能在构造器中,因为构造器调用晚于类的加载
* public static final double TAX_RATE3;
* public BB() {
* TAX_RATE3 = 3.3;
* }
*/
}
//final 对象不能继承,但是可以实例化
final class CC{
}
//如果不是final类但是含有final方法,则该方法虽然不能重写,但是可以被继承。
class DD {
public final void cal(){
System.out.println("cal()方法");
}
}
class EE extends DD{
}
输出结果
cal()方法
-
如果用
final
修饰了一个类,一般就不用final
修饰类中的方法。虽然语法上没问题,但是final
修饰类后已经不能被继承,其方法也肯定不能被重写,再用final
修饰有点画蛇添足。 -
final
和static
可以一起用,效率高,编译器会对其作底层优化,不会加载类但是可以使用变量。 -
包装类(
Integer,Double,Float,Boolean
等)都是final
类,String
也是final
类(Idea中 ctrl+b 查看源码)
//FinalDetail02.java
public class FinalDetail02 {
public static void main(String[] args) {
System.out.println(BBB.num);
}
}
final class AAA{
public final void cry(){}//一般final类中不用final修饰方法
}
class BBB{
public static int num = 1000;
//public final static int num = 1000;
static {
System.out.println("BBB的静态代码块");
}
}
输出结果
//BBB类中没有用final修饰num
BBB的静态代码块
1000
//BBB类中用final修饰num
1000
练习
public class Something {
public int addOne(final int x){//正确,final可以修饰形参
++x;//错误,final变量不能修改
return x+1;//可以,因为x本身并未改变
}
}