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。