`

说说final

 
阅读更多

final这个关键字从学Java开始就有提及。它可以用来修饰class, method, method parameter,variable等。这里主要说说最后这一种。

对于有final 修饰的variable, 无论是instance variable 还是local variable, 其含义是说(一般)一经初始化和赋值,其值就无法改变。这里,对于instance variable, 我们说,这“初始化和赋值”可能是在声明时就完成的,也可以是在构造函数中完成的。

然而,这个一般无法改变的值却是可以改变的。在JSR 133 中提到了用反射改变final 的instance field 的方法。这里截取的是那里面的例子:

classA...{
finalintx;
A()
...{
x
=1;
}

intf()...{
returnd(this,this);
}

intd(Aa1,Aa2)...{
inti=a1.x;
g(a1);
intj=a2.x;
returnj-i;
}

staticvoidg(Aa)...{
//usesreflectiontochangea.xto2
}

}

在JDK1.4 以及它以前的版本中,这种方法是行不通的。而在JDK 5 中,这种方法却可行的。具体做法是分别调用Field 的setAccessible(true) 方法和setX 方法进行赋值。

但是,这种方法可能会因为reorder 导致问题。JSR133 中说到:

... Another problem is that the semantics is designed to allow aggressive optimization of final fields.
Within a thread, it is permissible to reorder reads of a final field with calls to methods that may
change final fields via reflection.

所以,在JSR 133 中,提出了Final Field Safe Context 的概念。这个名词的意思是,在这个context 中,可以保证不会发生reorder 的现象。但奇怪的是,现在JVM 的实现中,似乎没有为这个语义定义关键字。

说到final, 顺便说一下static final. static final 在初始化以后,几乎都不能改变。这里说“几乎” 的原因是有例外:

Static final fields may only be modified in the class initializer that defines them, with the exception
of the java.lang.System.in, java.lang.System.out, and java.lang.System.err static fields, which can be modified by the java.lang.System.setIn, java.lang.System.setOut, and java.lang.System.setErr methods.

另外,顺便说一下,对于有无static 修饰的final field, 其在JVM 内部的初始化函数是不同的。这个有兴趣的可以看一下后面的参考文档。

最后要说的是所谓值“不能改变”的意思。概括的说,对于primitive 类型的变量,一旦声明为final, 除了上面的情况,初始化后就不能改了。而对于对象类型的field, “不能改变”的是它的引用。要理解这句话的意思,请看一下这段代码:

packagecom.dproxy;

importjava.util.ArrayList;

publicclassFinalChangeTest{
publicfinalinta=3;

publicfinalObjectb=null;

publicfinalStringc="abc";

publicfinalStringBufferd=newStringBuffer("a");

publicfinalArrayListe=newArrayList();

publicfinalTestClassf=newTestClass();

publicfinalint[]g=newint[3];

publicstaticvoidmain(Stringargs[]){
FinalChangeTesttest
=newFinalChangeTest();

//test.a=4;//error
//test.b="";//error

//test.c="";//error

//test.d=test.d.append("ttt");//error
test.d.setCharAt(0,'c');

test.e.add(
"");

//System.out.println(test.f.i);//1
test.f.i=2;
//System.out.println(test.f.i);//2

test.g[
0]=3;
}

classTestClass{
publicinti=1;
}

publicvoidfinalVarTest(){
finalinta=3;

finalObjectb=null;

finalStringc="abc";

finalStringBufferd=newStringBuffer("a");

finalArrayListe=newArrayList();

finalTestClassf=newTestClass();

finalint[]g=newint[3];

//a=2;//error
//b="";//error
//c="";//error

d.setCharAt(
0,'c');

e.add(
"");

f.i
=0;

g[
1]=2;


}
}

上面代码里注释部分的句子都是无法通过编译的。对比这个,读者可以理解一下。

参考:

JSR133

http://www.cs.umd.edu/~pugh/java/memoryModel/archive/2398.html

http://dev2dev.bea.com.cn/bbsdoc/20060704286.html

分享到:
评论

相关推荐

    B2C电子商务云计算时代-Final

    阿里巴巴要开发云计算!讲述云计算的含义!说说云计算

    java 短信发送 smslib RXTX 自动串口检测 下载

    自己写一个小程序,我在java1.6.0_10;smslib-v3.4.5下运行成功,主要是以下几个类. Level_Final_Serial.java:串口底层操作 ...http://blog.csdn.net/yangzl0123/archive/2010/03/02/5339263.aspx说说您的看法).

    说说Java的枚举类型

    enum实现  JDK5中提供了Java枚举类型的实现,与其说是一种新类型,... public final class Season extends Enum { public static Season[] values() { return (Season[])$VALUES.clone(); } public static Season

    java面试宝典

    10 使用final关键字修饰一个变量时 是引用不能变 还是引用的对象不能变 11 11 " "和equals方法究竟有什么区别 11 12 静态变量和实例变量的区别 12 13 是否可以从一个static方法内部发出对非static方法...

    Java面试宝典2014版

    3、说说&和&&的区别。 4、在JAVA中如何跳出当前的多重嵌套循环? 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么...

    java 短信发送 smslib RXTX 自动串口检测 下载 最新

    http://blog.csdn.net/yangzl0123/archive/2010/03/02/5339263.aspx说说您的看法). 时间:2010-3-3 12:15 ********************************************************************** smslib版本已经更新:...

    java开发面试题及答案

    Q1:简单说说Java有哪些数据类型 答:①分为基本数据类型和引用数据类型。②基本数据类型包括:数值型(byte、short、int、long、float、double),字符型(char)以及布尔型(boolean)。除了基本类型外,其他数据...

    安卓java读取网页源码-questions:自问自答

    final 修饰符的理解 说说你对泛型的理解 泛型中 extends 和 super 的区别 描述下 Java 中的异常处理机制 什么是 HashMap,描述下其实现原理 HashMap、Hashtable 和 HashSet 这三者有什么联系和区别 列举下 Java 的...

    【后端】java基础(5.4)java高级基础之java的修饰符——非访问控制符

    上章讲了访问控制符,这章开始讲非访问控制符。 java中的非访问修饰符的作用各不一样,据我所知常用的有六种: static final abstract ...首先我们来说说static: 被static修饰的方法我们称为静态方

    Java面试题.docx

    6、final,finally,finalize的区别 7、Serializable 和Parcelable 的区别 8、静态属性和静态方法是否可以被继承?是否可以被重写?以及原因? 9、成员内部类、静态内部类、局部内部类和匿名内部类的理解,以及...

    KoishiEx:恋恋のEX兔子版源代码以及KoishiExAPI源代码-代

    EXAPI是完全开源的,可以随意使用(不过似乎要设置一下ZLIB和LIBPNG相关的一些林林总总东东,据说说调试版本需要忽略特定库libcmt.lib等),如果大家发现有什么BUG或有什么帮助改进API的想法可以联系我对于VS2015...

    Java面试宝典

    3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

    java面试总结

    3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

    Java问题宝典2012版

    3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

    java 面试常问的问题 如何回答

    3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【基础】final, finally, finalize的区别 24 【基础】Java 中定义常量的几种方法 25 【基础】什么时候使用字节流?什么时候用字符流? 26 【基础】GBK与UTF-8的区别 26 【基础】static、final、const的区别 26 final...

    Java面试宝典2011版

    3、说说&和&&的区别。 4、在JAVA中如何跳出当前的多重嵌套循环? 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

    Java面试宝典2017.zip

    3、说说&和&&的区别。 8 4、在JAVA中如何跳出当前的多重嵌套循环? 8 5、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 9 6、short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有...

Global site tag (gtag.js) - Google Analytics