简单聊聊java中的final关键字
简单聊聊java中的final关键字
日常代码中,final关键字也算常用的。其主要应用在三个方面:
1)修饰类(暂时见过,但是还没用过);
2)修饰方法(见过,没写过);
3)修饰数据。
那么,我们主要也是从一下几个方面探讨一下,主要是第三点。
一、final修饰类和方法
final修饰的类不可被继承(例如: String, Integer, Double, ....);
final修饰的方法不可被重写(例如: AtomicInteger中的大部分方法)
二、final修饰数据
1. final修饰变量
分为局部变量和全局变量而言.如果是全局变量,不管你用不用,都必须而且只能赋值一次;
例如:
public class FinalTest {
private final int i;
}
如果不赋值,就会报编译错误: Variable "xxx" might not have been initialized。
如果是局部变量,如果不使用,可以不赋值。(当然,你得保证你的项目经理不会打死你)。
1.1 final修饰的基本数据类型和不变对象(例如: String, 包装类以及jdk8新的日期时间类库)那就是真的什么都不能该变了(引用与对象之间的引用关系,对象的内容(基本类型就是值)的值都不能改变). 例如:
public class FinalTest {
public static void main(String[] args) {
final int a = 10;
final LocalDate localDate = LocalDate.now();
}
}
如果再对a或者localDate进行赋值:就会报编译错误: cannot assign a value to final variable 'xxx'.
可以说,final对不可变对象的引用的修饰和对基础类型的引用的修饰含义几乎是一样的。
1.2 对于可变对象而言(常用的StringBuilder, 各种常见(List, Set, Map)的集合实现类),final仅仅只能保证引用和对象之前的引用关系不变,无法确保对象的内容(例如字段的值,容器内元素的个数)不变.
public class FinalTest {
public static void main(String[] args) {
final StringBuilder sb = new StringBuilder("sb ");
System.out.println("sb: " + sb);
sb.append("changed");
System.out.println("sb: " + sb);
}
}
-------------------------------------------------------------------------------
输出:
sb: sb
sb: sb changed
3. final修饰的值类型(8种基本数据类型 + String)将会优化为编译期常量
此处我们利用String的特性来测验一下:
public class FinalTest {
public static void main(String[] args) {
String a = "a";
String ab = a + "b";
System.out.println(ab == "ab");
final String finalA = "a";
String finalAB = finalA + "b";
System.out.println(finalAB == "ab");
}
}
-------------------------------------------------------------------------------
输出:
false
true
此处,我们可以对反编译FinalTest.class文件:
1 public class FinalTest {
2 public FinalTest() {
3 }
4
5 public static void main(String[] args) {
6 String a = "a";
7 String ab = a + "b";
8 System.out.println(ab == "ab");
9 String finalA = "a";
10 String finalAB = "ab";
11 System.out.println(finalAB == "ab");
12 }
13 }
对比第7行和第10行发现,第7行变量ab的值在编译期还是未知的(实际上在运行期,第7行的代码是这样执行的:
String ab = new StringBuilder("").append(a).append("b").toString;
而在StringBuilder#toString()方法内,new了一个新的String实例,因此ab 和 "ab"不是一个实例,所以第8行输出false.),而第10行变量finalAB的值在编译期就已知了,由于String常量池的缓存特性,使得finalAB和"ab"是同一个实例,所以第11行输出true.
这一点,有时候会带来一些问题。例如下面的例子:
1 class A{
2 public static final int A = 10;
3 }
4
5
6 class B{
7 public B(){
8 System.out.println(A.A);
9 }
10 }
从源代码中,可以看到class B和class A有些关系。但是实际上,编译之后的class字节码,类A 和类B没有任何关系。编译之后,第8行A.A已经被替换为10了。如果这个时候,修改了这个A中常量的值,然后仅仅对A重新编译,就会导致类B的class文件中依然是10.这可能给程序运行代码一些问题。
final修饰方法参数
`1这个在jdk中少见,但是在框架代码中常常见到.基本作用也就是防止方法调用者对参数在做赋值(其实这也是一种约定吧). 例如这样的场景: 现在有一组任务需要执行(任务可以并行),在这组任务全部执行完成之后,需要做一次清理缓存的操作; 可能的代码是这样的
List<Task> tasks = ...;
CountDownLatch countDoenLatch = new CountDownLatch(tasks.size());
for(Task task : tasks){
//线程池异步执行
WORKER.submit(task);
}
cleanCache(countDownLatch);
-----------------------------------------------------------------------------------------------------
public void cleanCache(final CountDownLatch countDownLatch){
countDownLatch.await();
...
}
此处cleanCache()方法中的参数CountDownLatch就需要使用final修饰。(如果对countDownLatch重新赋值,后续调用countDownLatch.await()会导致无限期等待)
小结:
final在修饰引用的时候,仅仅只能确保引用能且只能和某个对象建立引用关系(基本类型的值), 至于引用所指向的对象的内容是否可以改变,和这里的final没有任何关系,而是和这个对象是否是不变对象有关。 (通俗的将,使用final修饰某个引用的时候,这个final能够管得着的仅仅只是这个引用, 至于这个引起所指向的对象可不可变,它管不着。)
简单聊聊java中的final关键字的更多相关文章
- 浅析Java中的final关键字(转载)
自http://www.cnblogs.com/dolphin0520/p/3736238.html转载 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括 ...
- 关于Java中的final关键字
Java中的final关键字是用来限制用户行为的,说白了,就是用来限制我们这些程序员的.final可以用来修饰:变量.方法.类. 1)Java final variable final用来修饰变量时, ...
- 深入理解Java中的final关键字
Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方法和类声明为final代表了什么?使用final的好处是什么?最后也有一些使 ...
- 浅析Java中的final关键字
浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- (转)深入理解Java中的final关键字
转自:http://www.importnew.com/7553.html Java中的final关键字非常重要,它可以应用于类.方法以及变量.这篇文章中我将带你看看什么是final关键字?将变量,方 ...
- [转载]浅析Java中的final关键字
浅析Java中的final关键字 谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来 ...
- 转载:浅析Java中的final关键字
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...
- java中的final关键字
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...
- 浅析Java中的final关键字(转)
谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法.下 ...
随机推荐
- three.js 实现全景以及优化(2)
继昨天全景实现后,再做了一个全景图切换实验; code:https://github.com/Thinkia/threejs_/blob/master/test/test1-panorama/inde ...
- Java中instanceof关键字的用法
Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例.instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例. instanc ...
- [总结] 第二类Stirling数
上一道例题 我们来介绍第二类Stirling数 定义 第二类Stirling数实际上是集合的一个拆分,表示将n个不同的元素拆分成m个集合的方案数,记为 或者 .和第一类Stirling数不同的是,集合 ...
- 设置placeholder字体的颜色
::-webkit-input-placeholder { /* WebKit browsers */ color:#999; } :-moz-placeholder { /* Mozilla Fir ...
- python3.X中的循环
获取数字范围: range() 在python3.x中使用range(): >>> list(range(7)) [0, 1, 2, 3, 4, 5, 6] >>> ...
- Android Intent 基本使用及对象构成
Intent基本使用 Intent可以理解为不同组件通信的媒介或者信使. Intent可以启动一个Activity,也可以启动一个Service,还可以发起一个广播Broadcast. 具体方法如下表 ...
- CSS美化网页元素
<span>标签 </span>属性名 含义 举例font-family 设置字体类型 font-family:"隶书"font-size 设置字体大小 f ...
- Mac下安装virtualenv, 并在PyCharm中使用
今天在安装一个leader写的package的时候,同事建议安装到虚拟环境中,再在PyCharm里使用该虚拟环境即可.此处记录下经过: 开发Python应用的时候,有时会遇到不同的Python应用依赖 ...
- Beta冲刺集合
1.Day1 http://www.cnblogs.com/bugLoser/p/8075868.html 2.Day2 http://www.cnblogs.com/bugLoser/p/80758 ...
- 201621123031 《Java程序设计》第10周学习总结
作业10-异常 1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 1.捕捉异常 Java中的异常捕获结构由try.catch和finally三个部分组成.其中try语句 ...