final的深入理解 - final数据
先通过例子看一看:
package com.sotaof.testfinal;
public class Value {
int i;
public Value(int i){
this.i = i;
}
}
package com.sotaof.testfinal;
import java.util.Random;
public class FinalData {
private static Random rand = new Random(47);
private String id;
public FinalData(String id) {
this.id = id;
}
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
public static final int VALUE_THREE = 39;
private final int i4 = rand.nextInt(20);
static final int INT_5 = rand.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22);
private static final Value VAL_3 = new Value(33);
private final int[] a = {1,2,3,4,5,6};
public String toString() {
return id + ": " + "i4 = " + i4 + ", INT_5 = " + INT_5;
}
public static void main(String[] args) {
FinalData fd1 = new FinalData("fd1");
//fd1.valueOne++; 这句代码会报错,因为final修饰的基本类型数值是不可以变化的
fd1.v2.i++; //这句代码不会报错,因为final修饰的v2对象自身是可以变化的
fd1.v1 = new Value(9); //这个代码是不会报错的,就是创建一个对象,v1没有用final修饰
for(int i = 0; i < fd1.a.length; i++) {
fd1.a[i]++; //这句代码也是不会报错的,因为数组也是对象,而final修饰的对象自身可以变化
}
//fd1.v2 = new Value(0); 这句代码会报错 ,因为v2是用final修饰的,final修饰的对象自身是可以变化的,
//但是final修饰的对象的引用是不可以变化的,所以再用v2创建对象,就说明v2的引用变化了,所以报错
//fd1.VAL_3 = new Value(1);和上边一样的道理
//fd1.a = new int[3];和上边一样的道理
//刚才那三段代码都是一个意思,就是说final修饰的对象,这个对象的引用是不可以变化的
System.out.println(fd1);
System.out.println("Creating new FinalData");
FinalData fd2 = new FinalData("fd2");
System.out.println(fd1);
System.out.println(fd2);
}
}
1、我们不能因为某数据是final的就认为在编译时可以知道它的值。在运行时使用随机生成的数值来初始化i4和INT_5就说明了这一点。
2、这个实例也向我们展示了将final数值定义为静态和非静态的区别,这个区别只有当数值 在运行时内 被初始化时 才会显示(这句话不容易理解,我将其用" "分开了,以方便阅读理解,细细品读),这是因为编译器对编译时数值一视同仁,当运行程序时就会看到这个区别。
3、在fd1对象1中i4的值是唯一的,在fd2对象中i4的值也是唯一的,但是fd1和fd2中的i4值就不一定相同了,因为如果只有final修饰的话,在每次创建对象时都会被初始化(网友解释:i4仅仅是final类型的,分别在fd1和fd2两个对象中各开辟一块空间);
4、不管是在fd1中,还是在fd2中,INT_5的值都是一样的,是不可以通过创建第二个FinalData对象而加以改变的,这是因为它是static的,在装载的时候,就被初始化,而不是每次创建新对象时都初始化(网友解释:static final 仅使用一段不能改变的空间,所以INT_5值不变)。
在这里为了方便大家更多的了解final的数据,这里附上一位网友的例子,觉得很不错(http://chihom.iteye.com/blog/233035)
下面的两个初始化例子
class InitalizedClass {
static {
System.out.println("You have initalized InitalizedClass!");
}
public static int inititalize_varible = 1;
}
public class TestInitializeClass {
public static void main(String[] args) {
System.out.println(InitalizedClass.inititalize_varible);
}
}
上面的结果是:
You have initalized nitalizedClass!
1
再看下面的例子
class InitalizedClass {
static {
System.out.println("You have initalized InitalizedClass!");
}
//和上面的例子唯一的差异就是此处的变量INITIALIZED_VARIBLE被声明为final
public final static int INITIALIZED_VARIBLE = 1;
}
public class TestInitializeClass {
public static void main(String[] args) {
System.out.println(InitalizedClass.INITIALIZED_VARIBLE);
}
}
上面的结果是:
1
这里大家会问:为什么两个例子执行结果不一样?
原因是第二个例子中的INITIALIZED_VARIBLE为编译期常量,它不会导致类的初始化,也就是说,我第一个例子中,"InitalizedClass.inititalize_varible"这句代码会进入InitalizedClass这个类中,并执行static那段儿代码;而第二个例子中,"InitalizedClass.INITIALIZED_VARIBLE"这句代码并不会进入InitalizedClass这个类中,那有人会说,不进入这个类中怎么可能调用到INITIALIZED_VARIBLE这个值呢?因为我这个程序在编译的时候就初始化了,内存中已经存在INITIALIZED_VARIBLE这个值了,所以不再需要调用InitalizedClass类,这样大家应该理解了吧。
我也是今天才有了一点儿的理解,不过还是有一个疑问,希望各位网友能帮忙解决:
private final int valueOne = 9;
private final int i = rand.nextInt(20);
这两个代码,分别是在什么时候初始化的,我的理解是,valueOne和 i 都是编译时常量,但valueOne在编译的时候就初始化了,编译的时候就知道valueOne的值了,而 i 则是在运行时进行初始化的,运行的时候才会知道它的值。
final的深入理解 - final数据的更多相关文章
- 深入理解final和static关键字
深入理解final和static关键字 参考:http://blog.csdn.net/qq1028951741/article/details/53418852 final关键字 final关键字可 ...
- 面试题系列:工作5年,第一次这么清醒的理解final关键字?
面试题:用过final关键字吗?它有什么作用 面试考察点 考察目的: 了解面试者对Java基础知识的理解 考察人群: 工作1-5年,工作年限越高,对于基础知识理解的深度就越高. 背景知识 final关 ...
- 深入理解final关键字
在了解了final关键字的基本用法之后,这一节我们来看一下final关键字容易混淆的地方. 1.类的final变量和普通变量有什么区别? 当用final作用于类的成员变量时,成员变量(注意是类的成员变 ...
- java基础4:深入理解final关键字
本文主要介绍了final关键字的使用方法及原理 具体代码在我的GitHub中可以找到 https://github.com/h2pl/MyTech 文章首发于我的个人博客: https://h2pl. ...
- Java面试题,深入理解final关键字
final关键字 final的简介 final可以修饰变量,方法和类,用于表示所修饰的内容一旦赋值之后就不会再被改变,比如String类就是一个final类型的类. final的具体使用场景 fina ...
- 深入理解final关键字以及一些建议
引子:一说到final关键字,相信大家都会立刻想起一些基本的作用,那么我们先稍微用寥寥数行来回顾一下. 一.final关键字的含义 final是Java中的一个保留关键字,它可以标记在成员变量.方法. ...
- Java中的内存处理机制和final、static、final static总结
Java中的内存处理机制和final.static.final static总结 装载自:http://blog.csdn.net/wqthaha/article/details/20923579 ...
- Java第11次作业:什么是继承?继承的好处?什么是覆写?super()?构造代码块?子父类初始化顺序? 抽象类能用final声明吗?final关键字声明类 方法 变量以及全局常量?抽象类的构造方法?
什么是继承? 继承是以父类为基础,子类可以增加新的数据或新的功能.子类不能选择性地继承父类.这种技术使得复用以前的代码非常容易. JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一 ...
- final修饰符(5)-final方法
final修饰的类的方法不能被重写,例如如果父类不希望子类重写某个方法,则可以使用final修饰符修饰该方法 在java的Object类里面有一个final方法:getClass(),因为Java不希 ...
随机推荐
- Java IO4:字符流进阶及BufferedWriter、BufferedReader
字符流和字节流的区别 拿一下上一篇文章的例子: 1 public static void main(String[] args) throws Exception 2 { 3 File file = ...
- c++ 指针的简单用法
对于指针,其实只需要明白几点就可以. 1.指针,是一个数值为地址的变量,这里尤其注意,指针变量的值是地址!就是例如40002这种像门牌号的地址值,其实就是内存中的一个编号. 2.&,该符号的意 ...
- 【2】python核心编程 第四章-python对象
1.python对象 所有的Python 对像都拥有三个特性:身份,类型和值. 身份: 每一个对象都有一个唯一的身份标识自己,任何对象的身份可以使用内建函数id()来得到. 这个值可以被认为是该对象的 ...
- 手机三种SIM卡 你所不知道的剪卡“秘密”
SIM卡物理尺寸的发展是逐渐轻薄化,尺寸逐渐缩小的一个过程,最早手机中的卡都是2FF,2003年国际标准提出3FF,当前很多终端都使用这种形态的卡,4FF在2011年的国际标准会议中提出,2012年纳 ...
- 使用 asp.net Web API 2的坑
使用工具: Googl 浏览器+PostMan 插件 写了个 控制器 添加了个Action,结果呢?GET 方式请求没问题. POST一直,在服务器端获取不了参数...找了官方的文档 .各种雨里雾 ...
- maven添加oracle jdbc依赖
maven添加oracle jdbc依赖 由于Oracle授权问题,Maven不提供Oracle JDBC driver,为了在Maven项目中应用Oracle JDBC driver,必须手动添加到 ...
- UESTC_传输数据 2015 UESTC Training for Graph Theory<Problem F>
F - 传输数据 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit ...
- HDU1506(单调栈或者DP) 分类: 数据结构 2015-07-07 23:23 2人阅读 评论(0) 收藏
Largest Rectangle in a Histogram Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- hdu 4501 小明系列故事——买年货_二维背包
题目:你可以有v1元,v2代金券,v3个物品免单,现在有n个商品,商品能用纸币或者代金券购买,当然你可以买v3个商品免费.问怎么最大能买多少价值 题意: 思路二维背包,dp[v1][v2][v3]=M ...
- Zookeeper 3、Zookeeper工作原理(详细)
1.Zookeeper的角色 » 领导者(leader),负责进行投票的发起和决议,更新系统状态 » 学习者(learner),包括跟随者(follower)和观察者(observer),follow ...