Java中的final修饰符

  • final修饰变量时,表示该变量一旦获得了初始值就不可被改变。
  • final可修饰成员变量(包括类变量和实例变量)
  • final也可修局部变量、形参。
  • final成员变量(包括类变量和实例变量)必须由程序员显式初始化

final修饰成员变量

类变量:

初始值只能在以下两个地方之一指定:

  • 静态初始化块
  • 声明该类变量时

实例变量

初始值只能在以下三个地方之一指定:

  • 非静态初始化块
  • 声明该实例变量
  • 构造器

final修饰局部变量

  • 局部变量必须由程序员显式初始化
  • final修饰局部变量时没有指定默认值,可在后面代码中对其赋初始值,但只能一次。
  • 如果局部变量在定义时已指定默认值,则后面代码中不可再对其赋值。
public class A
{
    public void test(final int a)
    {
        //不能对修饰的形参赋值,下面语句非法
        a=5;
    }
}

final修饰引用类型变量

使用final修饰的引用类型变量不能被重新赋值
但可以改变引用类型变量所引用对象的内容
例:

public static void main(String[] args)
{
        final int[] iArr={5,6,12,9};
        System.out.println(Arrays.toString(iArr));
        Arrays.sort(iArr);
        System.out.println(Arrays.toString(iArr));
        //下面对数组元素赋值合法
        iArr[2]=-8;
        System.out.println(Arrays.toString(iArr));
        //下面这句对final修饰的引用类型变量重新赋值,非法
        iArr=null;
}

例:
假设有Person类

public static void main(String[] args)
{
    final Person p=new Person(20);
    //改变Person对象的age实例变量,合法
    p.setAge(11);
    //对final修饰的引用类型变量重新赋值,非法
    p=null;
}

可执行“宏替换”的final变量

final修饰符的一个重要用途就是定义“宏变量”。
当定义final变量时就为该变量指定了初始值,而且该初始值可以在编译时就确定下来,
那么这个final变量本质上就是一个“宏变量”,
编译器会把程序中所有用到该变量的地方直接替换成该变量的值。

如下程序:

public static void main(String[] args)
    {

        final int a=5;
        System.out.println(a);  

    }

a变量指定初始值为5,
对于上面程序而言,变量a其实根本不存在,
当程序执行System.out.println(a);代码时,
实际转换为System.out.println(5);执行的

看下面程序:

public class StringJoinTest
{

    public static void main(String[] args)
    {
        //定义4个宏变量
        final int a=5+2;
        final double b=1.2/3;
        final String str="bbb";
        final String book="aaa:"+99.0;
        //下面的book2因为调用了方法,所以无法在编译时被确定下来
        final String book2="aaa"+String.valueOf(99.0);

        //因为book是宏变量,故输出true
        System.out.println(book=="aaa:99.0");
        //输出false
        System.out.println(book2=="aaa:99.0");
    }

}
/*
Java会使用常量池来管理曾经使用过的字符串,例执行
String a="Java";后,常量池中会缓存一个字符串"java"
如果程序再执行String b="Java"
系统会让b直接指向常量池中的"Java"字符串,
因此a==b,将返回true
*/

book2变量显示将数值99.0转换为字符串,但由于该变量的值需要调用String类的方法,故无法在编译时确定book2的值,故不会被当成“宏”处理。

再看下面程序:

public class FinalReferenceTest
{

    public static void main(String[] args)
    {
        //编译时,就已确定s2的值为"aaabbb",
        //系统会让s2直接指向常量池中缓存的"aaabbb"
        //故输出true
        String s1="aaabbb";
        String s2="aaa"+"bbb";
        System.out.println(s1==s2);//输出true

        //str1、str2只是普通变量,编译器不会执行“宏替换”,故输出false
        //编译器无法确定s3的值,也就无法让其指向字符串中缓存的"aaabbb"
        String str1="aaa";
        String str2="bbb";
        String s3=str1+str2;
        System.out.println(s1==s3);//输出false

        //因为加了final修饰,编译时会执行“宏替换”,故输出true
        final String str3="aaa";
        final String str4="bbb";
        String s4=str3+str4;
        System.out.println(s1==s4);//输出true
    }

}

只有定义该变量时指定初始值才会有“宏变量”的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值