Java final关键字

在Java中,我们用到的关键字很多,其中之一就是final,final有哪些用法,每种用法有怎样的特性呢?在这一篇文章中,我们就将细数final的用法。


根据上下文环境,Java的关键字final的含义存在着细微的区别,但是通常它指的是“这是无法改变的。”不想做改变可能出于两种理由:设计和效率。在平常的使用过程中我们可能会对其误用。

一般而言,final分为以下几类用法:

  • final数据
  • 空白final
  • final参数
  • final方法

1.final数据

有时我们需要告知编译器一块数据是恒定不变的,这有时候是很有用的,比如在下列情况时:

1.一个永不改变的编译时常量
2.一个在运行时被初始化的值,而你不希望它被改变

对于基本类型,final使数值恒定不变;而用于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它改为指向另外一个对象。然而,对象其自身却是可以修改的。

对于一个既是static又是final的域只占据一段不能改变的存储空间

以下是对于一般类型final域和static final域的测试代码:

import java.util.Random;

class FinalData{
    private static Random random=new Random();
    private int valueOne=10;
    private final int valueTwo=20;
    private final int valueThree=random.nextInt(50);
    static final int valueFour=random.nextInt(50);
    
    public void setValueOne(int valueOne) {
        this.valueOne = valueOne;
    }
    
    public void show(){
        System.out.println("valueOne="+valueOne+"  valueTwo="+valueTwo+"  valueThree="+valueThree+"  valueFour="+valueFour);
    }
}

public class TestFinal {
    public static void main(String[] args){
        FinalData data1=new FinalData();
        data1.show();
        data1.setValueOne(22);
        data1.show();
        //在这里,由于其他数值都是final修饰,所以不可变,无法使用set方法对它们进行设置值
        //在这里,由于使用了random随机数,下面将演示用final修饰和static final修饰的区别
        FinalData data2=new FinalData();
        data2.show();
        data1.show();
    }
}

测试结果如下所示:

valueOne=10  valueTwo=20  valueThree=5  valueFour=19
valueOne=22  valueTwo=20  valueThree=5  valueFour=19
valueOne=10  valueTwo=20  valueThree=0  valueFour=19
valueOne=22  valueTwo=20  valueThree=5  valueFour=19

从结果我们能够知道对于 “final” 基本类型,它是不可变的,然而对于重写 “new” 的时候,可以改变,但是如果是使用的是 “static final” ,那么它的地址数据块都不变,即使用 “new” 都没有改变。


那么对于 “final” 的数据引用呢?下面我们也会通过代码注释方式讲解。

代码如下:

class FinalObject{
    int i;
    void FinalObject(int i){
        this.i=i;
    }

    public void show(String s) {
        System.out.println(s+i);
    }
}

public class TestFinalObject {
    public static void main(String[] args){
        final FinalObject finalObject=new FinalObject();
        finalObject.FinalObject(10);
        finalObject.show("finalObject 输出为:");

        FinalObject finalObject_0=new FinalObject();
        finalObject_0.FinalObject(30);
        finalObject_0.show("finalObject_0 输出为:");

        FinalObject finalObject_1=new FinalObject();
        finalObject_1.FinalObject(20);
        finalObject_1.show("finalObject_1 输出为:");

        //finalObject=finalObject_1;  finalObject使用了final关键字,无法让它指向另一个对象
        finalObject_0=finalObject_1;
        finalObject_0.show("finalObject_0指向finalObject_1后的输出为:");

    }

}

测试输出结果为:

finalObject 输出为:10
finalObject_0 输出为:30
finalObject_1 输出为:20
finalObject_0指向finalObject_1后的输出为:20

我们能发现,对于 “final” 的对象引用,我们不能改变它的原有引用。


2.空白final

在Java中,允许生成“空白 “final” ,所谓空白final是指被声明为 “final” 但又未给定初值的域。无论什么情况,编译器都确保空白 “final” 在使用前必须被初始化。

“空白final” 在关键字 “final” 的使用上提供了更大的灵活性。

下面是代码示例:

class Poppet{
    private int i;
    Poppet(int i1){i=i1; }
    public String toString(){
        return "   Poppet i="+i;
    }
}
class BlankFinal{
    private final int i=10;
    private final int final_0;
    private final Poppet poppet;

    public BlankFinal(){
        this.final_0 = 10;
        poppet=new Poppet(10);
    }

    public BlankFinal(int final_0) {
        this.final_0 = final_0;
        poppet=new Poppet(final_0);
    }
    public void show(){
        System.out.println("i="+i+"  final_0="+final_0+" "+poppet);
    }
}

public class TestBlankFinal {

    public static void main(String[] args){
        BlankFinal blankFinal=new BlankFinal();
        blankFinal.show();
        BlankFinal blankFinal_1=new BlankFinal(50);
        blankFinal_1.show();
    }
}

测试输出结果为:

i=10  final_0=10    Poppet i=10
i=10  final_0=50    Poppet i=50

3.final参数

在Java中允许在参数列表中以声明的方式将参数指明为 “final” 。这意味着你无法在方法中更改参数引用所指向的对象。

具体代码测试如下:

class First{
    public void show(){
        System.out.println("first class!");
    }
}


public class TestFinalParam {
    First g;
    void with(final First first){
        //first=new First();  报错,不能对传入的first进行更改
        g=first;//这种允许,这个操作没有对first进行更改
    }
    int  f(final int i){
        //i++;   final修饰的值不能改变
        return i+1;//在这里没有修改i的值,所以被允许

    }
    public static void main(String[] args){
        TestFinalParam testFinalParam=new TestFinalParam();
        First first=new First();
        System.out.println(testFinalParam.f(36));
        testFinalParam.with(first);
        testFinalParam.g.show();
    }
}

代码测试结果为:

37
first class!

对于 “final” 参数,你可以读,但是不能修改它。


4.final方法

一般使用 “final” 方法的原因有两个:
1.把方法锁定,以防任何继承类修改它的含义
2.是由于效率,在过去,使用final能在一定程度上提高效率,但是现在都不那么做了

对于 “final” 和上面讲的其他 “final” 基本类似,所以这里不再进行代码示例,如果有意向,可以自己去试试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值