简单聊聊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这个关键字的用法.下 ...
随机推荐
- web前端加载优化-减少HTTP请求 (细节与办法)
减少HTTP请求. 因为手机浏览器同时响应请求为4个请求(Android支持4个,iOS 5后可支持6个),所以要尽量减少页面的请求数,首次加载同时请求数不能超过4个.a) 合并CSS.JavaScr ...
- 【Django】模型层说明
[Django模型层] 之前大概介绍Django的文章居然写了两篇..这篇是重点关注了Django的模型层来进行学习. ■ 模型定义 众所周知,Django中的模型定义就是定义一个类,其基本结构是这样 ...
- 单例模式双重检验锁的判断是否为null的意义
关于双重检验锁首先简单来看一个小例子: public class Singleton{ private static Singleton instance = null; private Single ...
- logback常用配置详解及logback简介
logback 简介(一) Ceki Gülcü在Java日志领域世界知名.他创造了Log4J ,这个最早的Java日志框架即便在JRE内置日志功能的竞争下仍然非常流行.随后他又着手实现SLF4J 这 ...
- Hie with the Pie
Hie with the Pie poj-3311 题目大意:n+1个点,伪旅行商问题. 注释:n<=10. 想法:咳咳,第一道状压dp,下面我来介绍一下状压dp. 所谓dp,就是动态性决策规划 ...
- python web开发-flask中sqlalchemy的使用
SqlAlchemy是一个python的ORM框架. 在flask中有一个flask-sqlalchemy的扩展,使用起来很方便. 1. 创建一个sqlalchemy的Model模块 创建 ...
- 爬虫(BeautifulSoup--select--class的选择)
<div class="item name" title="中央公园"> <a href="/Attraction_Review-g ...
- 用python程序来画花
from turtle import * import time setup(600,800,0,0) speed(0) penup() seth(90) fd(340) seth(0) pendow ...
- python替换残缺的多域名图片网址
在获取网站真是图片的时候,经常遇到图片链接残缺问题. 例如下图所示的情况: img标签中的图片链接是残缺的,如果这个网站域名又是多种情况的话,比如 http://sports.online.sh.cn ...
- 201621123040《Java程序设计》第4周学习总结
1.本周学习总结 1.1写出你认为本周学习中比较重要的知识点关键词 关键词:继承 多态性 基本语法 重新定义Override 1.2尝试使用思维导图将这些关键词组织起来.注:思维导图一般不需要出现过多 ...