Java学习篇之---修饰符final详解

Java学习篇之---修饰符final详解

        最近又翻看了一遍Java的基础知识,发现当初自己关于修饰符final的理解就曾经迷茫过,为了帮助Java初学者更好度过迷茫期,特此献上此文(此文将重点讲解final修饰的变量,至于final修饰的类和方法,由于比较简单,就不再下面列出了)。

一、概述:

        final关键字可用于修饰类、变量和方法。final修饰变量时,表示该变量一旦获得了初始值就不可被改变(可以赋初值,但是不可以被改变),final既可以修饰成员变量(包括类变量和实例变量),也可以修饰局部变量、形参。

二、final成员变量:

1) 类变量:

final修饰类变量,要么在定义该类变量时指定初始值;要么在静态初始化块中指定初始值。

/*正确代码演示*/
public class FinalClassTest{
    final static int a=210;//在定义该类变量时指定初始值;
    final static int b;

    static{
        b=211;//在静态初始化块中指定初始值;
    }
}

/*错误代码演示*/
public class FinalClassErrorTest{
    final static int aa=110;
    final static int bb;
    //系统不会为final成员变量(类变量和实例变量)进行隐形初始化;而此类变量既没有在定义时指定初始值,又没有在静态初始化块中指定初始值,所以非法。

    final static int cc;

    static{
        aa=111;//类变量已经定义了初始值,不能再次赋值,因此此语句非法;
    }

    public void finalClassChange(){
        bb=112;//在普通方法中为类变量赋值,因此此语句非法;
    }
}

 

2) 实例变量:

final修饰实例变量,要么在定义该实例变量时指定初始值;要么在普通初始化块中指定初始值;要么在构造器中指定初始值。

/*正确代码演示*/
public class FinalInstanceTest{
    final int c=310;//在定义该实例变量时指定初始值;
    final int d;
    final int e;

    {
        d=311;//在普通初始化块中指定初始值;
    }
    
    public FinalInstanceTest(){
        e=312;//在构造器中指定初始值;
    }
}

/*错误代码演示*/
public class FinalInstanceErrorTest{
    final int cc=410;
    final int dd;
//系统不会为final成员变量(类变量和实例变量)进行隐形初始化;而此实例变量既没有在定义时指定初始值,又没有在普通初始化块中指定初始值,又没有在构造器中赋值,所以非法。

    final int ee;

    {
        cc=411;//实例变量已经定义了初始值,不能再次赋值,因此此语句非法;
    }

    public void finalInstanceChange(){
        dd=412;//在普通方法中为实例变量赋值,因此此语句非法;
    }

    public FinalInstanceErrorTest(){

    }
}
 

三、final局部变量:

系统不会对局部变量进行隐形初始化,需要程序员显性初始化。

public class FinalLocalTest{

    public void invokTest(final int f){

        f=510;//对final修饰的形参变量赋值,非法;

        //该方法被调用时,由系统根据传入的参数来对形参完成初始化;

    }

    public void mainTest(){

        final int g=511;//定义final变量时指定初始值,合法;

        final int h;

        h=512;//第一次赋初始值,合法;

    }
}

四、final修饰基本类型变量和引用类型变量的区别:

final修饰基本类型变量时,不能对基本类型变量重新赋值;对于引用类型而言,它保存的只是一个引用,final只保证这个引用类型变量所引用的地址不变,即一直引用同一个对象,但是这个对象的成员可以改变;

class Student{
    privte int age;
    public Student(int age){

        this.age=age;

    }
    //此处省略age的setter和getter方法;
}

public class FinalReferenceTest{

    public static void main(String[]  args){
        //final修饰数组变量,iArray是一个引用变量;
        final int[] iArray={5,6,7,8};
        Arrays.sort(iArray);//对数组元素进行排序,合法;
        iArray[3]=9;//对数组元素赋值,合法;
        iArray=null;//对iArray重新赋值,非法;
        final Student st=new Student(21);
        st.setAge(23);//改变Student对象的age实例变量,合法;
        st=null;//对st重新赋值,非法;
    }
}


五、可执行"宏替换"的final变量:

对于一个final变量而言,不管是类变量、实例变量还是局部变量,只要该变量满足以下三条,则final变量就不再是一个变量,而是相当于是一个直接值:

1、使用final修饰符修饰;

2、在定义该final变量时指定了初始值;

3、该初始值可以在编译时就确定下来。

public class MacroFinalTest{
    public static void main(String[] args){
        final String domainName="pplns.com";
        final String domain="pplns"+".com";
        System.out.println(domainName==domain);//返回值为true;

        final String domainPrefix="pplns";
        final String domainSuffix=".com";
        final String myDomain=domainPrefix+domainSuffix;
        System.out.println(domainName==myDomain);//返回值为true;
    }
}

 
public class MacroTest{ 
    public static void main(String[] args){ 
        String domainName="pplns.com"; 
        String domain="pplns"+".com"; 
        System.out.println(domainName==domain);//返回值为true;
        String domainPrefix="pplns"; 
        String domainSuffix=".com"; 
        String myDomain=domainPrefix+domainSuffix; 
        System.out.println(domainName==myDomain);//返回值为false;
    }
} 

 

以上特意用final修饰的变量和无final修饰的变量进行对比,从而发现不同之处。

Java通过一个常量池来管理曾经用过的字符串常量,例如执行String domain="pplns.com";语句之后,常量池中就缓存了一个字符串“pplns.com”;如果程序再执行String domainName="pplns.com";,系统将会让domainName直接指向常量池中“pplns”字符串,因此domain==domainName将返回true;但是在上例MacroTest类中,myDomain是由两个变量拼接而成,而变量在编译期间是不会确定下来,只有在运行期间才会确定下来,所以domainName==myDomain返回的是false;而在上例MacroFinalTest类中,domainPrefix和domainSuffix是由final修饰的变量,所以这两个变量在编译期间就会当作“宏变量”,即常量来处理,所以myDomain在编译期间实际是由"pplns"和".com"拼接而成,所以domainName==myDomain返回的是true。








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值