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。