Bootstrap

28、final关键字

一、使用到final的场景:

1、当不希望类被继承时,可以用final修饰

final class A{}

2、当不希望父类的某个方法被子类覆盖/重写时,可以用final修饰

class A{
    public final void hi(){}
}

3、当不希望类的某个属性的值被修改,可以用final修饰

class A{
    public final double TAX_RATE=0.08;
}

4、当不希望某个局部变量被修改,可以用final修饰

class A{
    public void cry(){
        final double NUM=0.01;
    }
}

二、细节:

1、final修饰的属性又叫常量,一般用XX_XX_XX来命名(大写)

2、final修饰的属性在定义时,必须赋初值,且以后不能再修改,赋值可以在如下位置之一赋初值:

(1)定义时

(2)在构造器中

(3)在代码块中

class AA {
    public final double TAX_RATE = 0.08;//1、定义时
    public final double TAX_RATE2;//2、在构造器中
    public final double TAX_RATE3;//3、在代码块中
    public AA() {
        TAX_RATE2 = 1.1;
    }
    {
        TAX_RATE3=8.8;
    }
}

3、如果final修饰的属性是静态的,则初始化的位置只能是:

(1)定义时

(2)在静态代码块

(3)不能在构造器中赋值(因为静态早于构造器)

4、final类不能继承,但可以实例化对象

final class AA{}

5、如果类不是final类,但含有final方法,则该方法虽然不能重写,但可以被继承

package final_;

public class FinalDetail01 {
    public static void main(String[] args) {
        new BB().cal();
    }
}
class AA{
    public final void cal(){
        System.out.println("cal()方法");
    }
}
class BB extends AA{}
//输出:cal()方法

4、5点小结:

final修饰的类,不能被继承,可以实例化

final修饰的函数不能被重写,可以被继承

6、一般来说,如果一个类已经是final类了,就没有必要再将方法修饰成final方法

(不能被继承,所以没有子类,所以不可能被重写,也就不需要用final修饰)

7、final不能修饰构造方法(即构造器)

8、final和static往往搭配使用,效率更高,不会导致类加载,底层编译器做了优化处理

(1)final+static,可以调用类的局部变量,而不会加载类

(2)public, static, final三个顺序没有要求,按习惯来

package final_;
public class FinalDetail01 {
    public static void main(String[] args) {
        System.out.println(BB.num);
    }
}
class BB{
    public final static int num=1000;//加了static后,只输出:1000,不会加载类,不会输出那句话
    static {
        System.out.println("BBB静态代码块被执行……");
    }
}

9、包装类(Integer,Double,Float,Boolean等都是final),String也是final类 

三、练习

1、

//我的答案:

//编写一个程序,能够计算圆形的面积,要求圆周率为3.14,赋值的三个方式都写
package final_;
import java.awt.geom.Area;
public class FinalExercise01 {
    public static void main(String[] args) {
        Area01 t1=new Area01(3.0);
        System.out.println(t1.area());
    }
}
class Area01{
    private final double PI1=3.14;
    private final double PI2;
    private final static double PI3;
    private double radius;
    static {
        PI3=3.14;
    }

    public Area01(double radius) {
        this.radius = radius;
        PI2=3.14;
    }

    public double getRadius() {
        return radius;
    }

    public void setRadius(double radius) {
        this.radius = radius;
    }
    public double area(){
        return PI1*radius*radius;
    }
}

//老师的答案:

package final_;
public class FinalExercise01 {
    public static void main(String[] args) {
        Circle circle=new Circle(5.0);
        System.out.println("面积="+circle.calArea());
    }
}
class Circle{
    private double radius;
    private final double PI=3.14;

    public Circle(double radius) {
        this.radius = radius;
        //PI=3.14;
    }
    {
        //PI=3.14;
    }
    public double calArea(){
        return PI*radius*radius;
    }
}
//输出:面积=78.5

2、

public class Something{
    public int addOne(final int x){
        ++x;//错误,原因是不能修改final x的值
        return x+1;//正确
    }
}
//形参不能是常量?
//这里不是这样的,这里传进来的参数相当于是在方法体里的局部变量,所以自然可以用final修饰

;