前面在讲解String时提到了final关键字,本文将对final关键字进行解析。

staticfinal是两个我们必须掌握的关键字。不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。下面我们来了解一下final关键字及其用法。

final从总体上来说是“不可变的”,可用于修改类、方法、变量。

一. final类

final修饰的类,该类不能被继承。当你确认一个类永远不会被继承或不想被继承,那么就可以用final修饰。

同样,对于接口(interface)和抽象类(abstract Class),其本就是为了“多态”而设计,自然无法用final关键字修饰

final类中的成员方法默认也被隐式指定为final方法。

二. final方法

final修饰的方法不可被重写。

例子:

/**
* 父类
* @author LH
*/
public class FinalDemo1 {
public final void test() { }
}

三. final变量

final变量包括成员变量和局部变量。变量类型包括基本数据类型、对象。

通过final修饰局部基本类型变量(及其包装类),数值一经初始化(可以定义时初始化,也可以在使用前初始化)不可改变。如:

final int a = 0;
a = 1;//报错
final int b;
b = 1;//编译通过

通过final修饰局部引用类型变量时,其引用的对象(内存地址)(可以定义时初始化,也可以在使用前初始化)不可改变,但对象中存放的数据可以改变

public static void main(String[] args) {
final String str1 = "helloWorld";
str1 = "helloChina";//编译出错,String的不可变性,此处返回的是新的对象引用。 final StringBuilder sb = new StringBuilder("hello");
sb.append("world");//编译通过 sb = new StringBuilder("China");//编译出错
}

final修饰的成员变量必须在定义的时候直接初始化,否则会编译出错

public class FinalDemo1 {
public final int age;//final修饰的基本类型,编译出错
public final int age1 = 20;//final修饰的基本类型,编译通过
public final StringBuilder address;// final修饰的引用类型,编译出错
public final StringBuilder address1 = new StringBuilder("中国");//final修饰的引用类型,编译通过
}

那么final变量与普通变量之间到底有何区别,看下面的例子

public static void main(String[] args) {
String str0 = "helloWorldChina";
String str1 = "helloWorld";
String str3 = str1 + "China";
System.out.println(str0 == str3);//false final String str2 = "helloWorld";
String str4 = str2 + "China";
System.out.println(str0 == str4);//true final String str5;
str5 = "helloWorld";
String str6 = str5 + "China";
System.out.println(str0 == str6);//false
}

str0 == str3运行结果为false,这是因为通过“+”生成了一个新的字符串对象,返回的引用地址和str0不再一样,这在《Java基础(三) String深度解析》中有讲解。

那么str0 == str4的执行结果为什么是true?

通过final修饰的变量,如果在编译期都可以知道确切值(定义变量的时候就初始化),那么在编译器会将其当做常量使用,所有用到该变量的地方就相当于直接使用该常量,String str4 = str2 + "China" 在编译期间都已经合并处理成String str4 = "helloWorldChina",因此str0与str4引用了常量池中同一个字符串字面量的地址,故而结果为true。

而str0 == str6的执行结果为false也很好理解

str5在编译期并不知道确切值,而是在使用之前才进行初始化,因此编译器无法事先进行合并处理,str6通过“+”生成了一个新的字符串对象,返回的引用地址和str0也不再一样。

而针对基本数据类型来说定义为final变量与普通变量,比较结果来说并无差异

public static void testint(){
int int0 = 8;
final int int1;
int1 = 4;
int int2 = int1 + 4;
System.out.println(int2 == int0);//true
}

因为基本数据类型并不存在引用传递的概念,基本类型变量也是字面常量,所以对基本类型的操作都是直接对值的操作,和引用不一样,比较的并非地址。

四. 总结

本文主要对final关键字的原理进行了讲解,同时对其基本用法进行了说明,包括final修饰的类,final修饰的方法和final修饰的变量,另外文中String变量通过==比较只是为了更加清晰的说明final原理,实际应用场景比较的时候还是用equals()方法,final也经常和static配合使用作为“全局常量”,若有不对之处,请批评指正,望共同进步,谢谢!

最新文章

  1. Lenovo K29 笔记本经常没声音解决方案Hotkey[gevu18ww].exe
  2. JavaScript下的setTimeout(fn,0)意味着什么?
  3. SQL SERVER错误:已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)
  4. git学习:多人协作,标签管理
  5. ie下如果已经有缓存,load方法的效果就无法执行.的解决方法
  6. 简单研究Android View绘制二 LayoutParams
  7. Redis & Python/Django 简单用户登陆
  8. TYVJ P1082 找朋友 Label:字符串
  9. 【Android】关于pix,dip,dip,sp等相关概念
  10. easyUI:ComboTree and comselector使用实例解析
  11. HDU ACM 1025 Constructing Roads In JGShining's Kingdom->二分求解LIS+O(NlogN)
  12. poj 2406Power Strings
  13. [Android]Can't create handler inside thread that has not called Looper.prepare()
  14. javascript中关于this的理解
  15. (转)java web 学习之路(学习顺序)
  16. Oracle DG测试failover和后续恢复报告
  17. JAVA调用WCF
  18. js判断是否为ie浏览器
  19. OpenLayer3调用天地图,拖拽后,地图消失的问题[已解决]
  20. springMVC源码分析--AbstractControllerUrlHandlerMapping(六)

热门文章

  1. Spring 的 ApplicationEvent and ApplicationListener
  2. 机器学习: t-Stochastic Neighbor Embedding 降维算法 (二)
  3. Qt常用函数 记录(update erase repaint 的区别)
  4. Boost智能指针-基础知识
  5. EF codefirst第一篇
  6. Atitit.Gui控制and面板----db数据库领域----- .比较数据库同步工具 vOa
  7. freemarker写select包(四)
  8. Spring综合Struts2
  9. 关于JSON 字段数据的直接查询
  10. window对象的方法