天天看點

Java基礎——final關鍵字

final作為關鍵字,可以分别用在類、方法和變量上,靈活運用可以得到不同的效果。

1. final類

類被final關鍵字修飾後就無法被繼承,繼承就會報錯。

2. final方法

方法被final關鍵字修飾後就可以直接調用,編譯時靜态綁定,已經确定是哪個類的方法,是以執行效率會相對其他方法要高,并且可以防止被繼承後重寫。

3. final變量

普通變量被final關鍵字修飾後就轉變為常量,值無法被修改;引用變量被修飾後,内容可以修改。

仔細觀察分析如下代碼:

public class KeyFinalMain {

    //定義靜态常量變量,便于内部調用。
    final static String KEY_FINAL_NAME = "HelloFinal";

    //final修飾類,類不允許被繼承。
    final static class UserModel {

        String name;
        String sex;
        int age;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

    }

    //UserModel已經被final修飾不能被繼承,以下代碼報錯。
//    class DroyModel extends UserModel{}

    class parent{
        public final void changeMethod(String name, String sex, int age){
            System.out.println("final方法");
        }
    }

    class sub extends parent{

        //final修飾的方法不可以被重寫,以下代碼報錯。
//        @Override
//        public void changeMethod(String name, String sex, int age){}
    }

    //方法1: 修改引用變量的内容,參數定義為普通變量和引用變量。
    private static UserModel changeParams1(String name, UserModel userModel){
        userModel.setName(name);
        return userModel;
    }

    //方法2: 修改引用變量的内容,參數定義為普通變量和引用變量。
    private static UserModel changeParams2(String name, UserModel userModel) {
        name = "ZhouDroy";
        userModel = new UserModel();
        userModel.setName(name);
        return userModel;
    }

    //方法3: 修改引用變量的内容,參數定義為final修飾的普通變量和引用變量。
    private static UserModel changeParams3(final String name, final UserModel userModel) {
        //當參數定義為final時,以下代碼報錯。
//        name = "Zhou Droy";
//        userModel = new UserModel();
        //但是可以改變引用變量的内容。
        userModel.setAge(36);
        return userModel;
    }

    public static void main(String[] args) {

        //A.
        String equStr = "2019新年快樂!";
        String text1 = "新年快樂!";
        final String text2 = "新年快樂!";

        String text = 2019+text1;
        String final_text = 2019+text2;
        System.out.println("text: "+text+"  比較結果:"+(equStr==text));
        System.out.println("final_text: "+final_text+"  比較結果:"+(equStr==final_text));

        //B.
        //當普通變量定義為fianl時,值不可以修改,以下代碼報錯。
//        KEY_FINAL_NAME = "cannot assign a value to final variable!";
        //初始化定義引用變量
        UserModel userModel = new UserModel();
        userModel.setName("DroyZhou");
        userModel.setSex("男");
        userModel.setAge(18);
        System.out.println("UserModel初始定義:  " + userModel.getName() + " " + userModel.getSex() + " " + userModel.getAge());

        //注意觀察1,2,3值,它們為什麼有相同和不同的值。
        UserModel userModel1 = changeParams1(KEY_FINAL_NAME, userModel);
        System.out.println("UserModel1: " + userModel1.getName() + " " + userModel1.getSex() + " " + userModel1.getAge());

        UserModel userModel2 = changeParams2(KEY_FINAL_NAME, userModel);
        System.out.println("UserModel2: " + userModel2.getName() + " " + userModel2.getSex() + " " + userModel2.getAge());

        UserModel userModel3 = changeParams3(KEY_FINAL_NAME, userModel);
        System.out.println("UserModel3: " + userModel3.getName() + " " + userModel3.getSex() + " " + userModel3.getAge());
    }
}
           

最終執行結果:

text: 2019新年快樂!  比較結果:false
final_text: 2019新年快樂!  比較結果:true
UserModel初始定義:  DroyZhou 男 18
UserModel1: HelloFinal 男 18
UserModel2: ZhouDroy null 0
UserModel3: HelloFinal 男 36
           
為什麼text和final_text值看上去一緻,但比較結果卻不同,因為equStr的值是指向常量池中的,而text2也是常量,生成的final_text也是常量直接指向常量池中的唯一值,是以他們是相等的;但是,text是由連結引用計算在堆上生成的,是以不相等為false。