1、如果一个数据既是static又是final,那么它会拥有一块无法改变的存储空间。

2、final data: 当final用于基本数据类型时,final让其值(value)保持不变,但是当用于object reference时,final仅让reference保持不变。也就是说当reference一旦被初始化用于代表某个对象时,便再也不能改变指向另一个对象,但对象本身的内容确实可以改变的。final对array的作用和对reference的作用一样。参考以下例子:

public class Test1{
private final int li_int=12;
private final InClass inClass1=new InClass(5);
private final InClass inClass2=new InClass(8);
public void modifiedFinal(int a){
//下面语句出现编译错误,不能修改final基本类型的值
//li_int = a;
//下面语句出现编译错误,不能将已经初始化的final变量指向另一个对象
//inClass1=inClass2;
//下面语句成功,虽然引用不能改变但final变量引用的对象本身内容是可以改变的
inClass1.mod(a);
}
class InClass{
int li_a=0;
public InClass(int a){
li_a=a;
}
public int mod(int b){
li_a=b;
return li_a;
}
}
public static void main(String args[]){
Test1 test1=new Test1();
test1.modifiedFinal(100);
System.out.println(test1.inClass1.li_a);
}
} 3、blank finals:java允许将数据成员声明为final,却不赋初值。但是,blank finals必须在使用之前初始化,且必须在构造函数中初始化。请参考以下例子: public class Test2{
//final变量一开始允许不赋值
private final int li_int;
public Test2(int a){
//下面语句编译通过,对定义为空的final变量的赋值必须在构造方法中进行,而且必须要赋值,不赋值也报错
li_int = a;
}
public int mod(int a){
//下面语句编译出错,对定义为空的final变量的赋值必须在构造方法中进行
//li_int = a;
return li_int;
}
} 4、final arguments: 声明arguments为final,可以保证该argument不能再被指向它处,当argment是基本数据类型时,就意味着值不能改变。参考以下例子: public class Test3{
private int li_int=12;
private InClass inClass1=new InClass(5);
private InClass inClass2=new InClass(8);
public void modifiedFinal(final int a,final InClass in){
//下面语句出现编译错误,不能修改final基本类型的值
//a = 15;
//下面语句出现编译错误,不能将已经初始化的final变量指向另一个对象
//in=inClass2;
//下面语句成功,虽然引用不能改变但final变量引用的对象本身内容是可以改变的
in.mod(a);
}
class InClass{
int li_a=0;
public InClass(int a){
li_a=a;
}
public int mod(int b){
li_a=b;
return li_a;
}
}
public static void main(String args[]){
int a=100;
//内部类初始化
Test3 test3=new Test3();
Test3.InClass in=test3.new InClass(30);
System.out.println(in.li_a);
test3.modifiedFinal(a,in);
System.out.println(in.li_a);
}
} 5、final methods: 可以锁住该method,不让继承类改变其意义(不允许子类覆写);允许编译器对此method作为inline method调用。参考以下例子: public class Test4{
private final int li_int=0;
public final int pub_fi_mod(){
return li_int;
}
protected final int pro_fi_mod(){
return li_int;
}
private final int pri_fi_mod(){
return li_int;
}
private int pri_mod(){
return li_int;
}
} public class Test5 extends Test4{
private int li_i=100;
//下面的方法编译出错,不能覆盖final方法,只针对public和protected,子类中方法与父类中private的方法名相同不是覆盖,与父类中同方法名的方法没有任何关系(除了名字相同)。
/*
public int pub_fi_mod(){
return li_i;
}
protected int pro_fi_mod(){
return li_i;
}*/
private final int pri_fi_mod(){
return li_i;
}
private int pri_mod(){
return li_i;
}
public static void main(String args[]){
System.out.println(new Test5().pri_mod());
}
} 6、fianl(method) vs private(method): class所有的private methods自然而然都是final,private methods仅仅是隐藏class中的某段程序代码而已,不能被overrid,即使子类中恰好有同名的method,也不会产生什么效果;其中两者的区别是在子类中可以出现与private方法有相同签名的方法,而public或protected的final方法不能被重写,但允许方法名相同但参数列表不同的重构方法出现。借用以上例子,将Test5修改后编译通过: public class Test5 extends Test4{
private int li_i=100;
//下面的方法编译出错,不能覆盖final方法
/*
public int pub_fi_mod(){
return li_i;
}
protected int pro_fi_mod(){
return li_i;
}
*/
//但允许参数列表不同的重构方法出现
public int pub_fi_mod(int a){
return li_i;
}
protected int pro_fi_mod(int a){
return li_i;
}
private final int pri_fi_mod(){
return li_i;
}
private int pri_mod(){
return li_i;
}
public static void main(String args[]){
System.out.println(new Test5().pri_mod());
}
} 7、final classes: 当把一个class声明为final时,也就决定了此class将不能被继承(比如String类,此类为final类,具体可以参见其实现java.lang.String)。final classes的methods可以是final,也可以是非final的;其中的数据成员可以是final的也可以不是,他们将服从final data的原则。参考以下例子: public final class Test6{
private final int li_int=0;
public int li_a=123;
public final int mod(){
return li_int;
}
public int pri_mod(){
return li_a;
}
public static void main(String args[]){
System.out.println(new Test6().pri_mod());
}
} //Test6是final类,所以Test7不能继承
public class Test7 extends Test6{
private int li_int=0;
} PS:从以上可以看出,final是将一个对象的地址不变,对基本类型的值保持不变(因为基本类型变量指向的物理地址存放value而对象变量指向的物理地址存放对象内容的地址)。 PS:以前读书时老师说java中final定义常量,只说对了一半,对基本类型是对的,对String也是对的,因为String虽然是对象,但不会出现String变量地址不变而其内容发生改变的情况(String是一个整体不能只改变其中的一个字符),所以也是对的,但对其他的对象只能保持其引用地址不变不能保证其内容不变,所以是错的。 再补充一些内容: 1、对final属性在声明时就赋值,而且赋的值是常量的话,那编译器会将所有用到此属性的地方都替换成常量,这个请参考下面的代码: package com.xx.dryr.test1; import java.lang.reflect.Field; public class Test1Class1{ public final int x = 100; public int f(Test1Class1 t1c11,Test1Class1 t1c12) throws Exception{ int i = t1c11.x; System.out.println("i's value is "+i); changeX(t1c11); int j = t1c12.x; System.out.println("j's value is "+j); return j - i; } public static void changeX(Test1Class1 t1c1) throws Exception{ Class clazz = t1c1.getClass(); Field fieldX = clazz.getDeclaredField("x"); fieldX.setAccessible(true); fieldX.setInt(t1c1, 300); System.out.println("fieldX's vlaue is "+fieldX.getInt(t1c1)); } public int test() throws Exception{ return f(this,this); } public static void main(String[] args) throws Exception{ Test1Class1 t1c1 = new Test1Class1(); System.out.println(t1c1.test()); } } 运行结果是: i's value is 100 fieldX's vlaue is 300 j's value is 100 0 虽然在changeX方法中,已经将x的值修改为300,但因为编译时所有使用到x的地方都使用100替换了,所以在运行时再怎么修改x的值都不会对使用到x的地方产生影响。 2、否则,对不是在编译时确定final属性值的情况下,final属性的值是可以改变的。请参考如下代码,对上面的代码稍微做了修改,让final属性x在构造方法中初始化: package com.xx.dryr.test1; import java.lang.reflect.Field; public class Test1Class1{ public final int x ; public Test1Class1(){ x = 100; } public int f(Test1Class1 t1c11,Test1Class1 t1c12) throws Exception{ int i = t1c11.x; System.out.println("i's value is "+i); changeX(t1c11); int j = t1c12.x; System.out.println("j's value is "+j); return j - i; } public static void changeX(Test1Class1 t1c1) throws Exception{ Class clazz = t1c1.getClass(); Field fieldX = clazz.getDeclaredField("x"); fieldX.setAccessible(true); fieldX.setInt(t1c1, 300); System.out.println("fieldX's vlaue is "+fieldX.getInt(t1c1)); } public int test() throws Exception{ return f(this,this); } public static void main(String[] args) throws Exception{ Test1Class1 t1c1 = new Test1Class1(); System.out.println(t1c1.test()); } } 运行结果是: i's value is 100 fieldX's vlaue is 300 j's value is 300 200
从上面的例子中可见,final属性的值还是可以被改变的,但只有在特殊情况下(没有在编译时被替换),使用特殊的方式(像反射这样的方式),final属性的值才可以被改变。所以说一般情况下说final属性的值是不允许被修改的还是可以说的,但必须得知道这些例外情况的。

java中final的意义的更多相关文章

  1. Java中final修饰符深入研究

    一.开篇 本博客来自:http://www.cnblogs.com/yuananyun/ final修饰符是Java中比较简单常用的修饰符,同时也是一个被"误解"较多的修饰符.对很 ...

  2. Java中final修饰的数据

    目录 Java中final修饰的数据 有初始值的final域 final+基本数据类型 final+引用数据类型 final与static final 空白final域 final修饰的参数 基本数据 ...

  3. Java中final的作用

    Java中Final可以被用于变量,方法,类.具体来说: 1, Final 变量 修饰主类型时,制定变量为常数,不希望被改变 修饰类类型时,表示变量的句柄不变,不能被指定指向新的变量 修饰参数时,参数 ...

  4. 深刻理解Java中final的作用(一):从final的作用剖析String被设计成不可变类的深层原因

    声明:本博客为原创博客,未经同意,不得转载!小伙伴们假设是在别的地方看到的话,建议还是来csdn上看吧(原文链接为http://blog.csdn.net/bettarwang/article/det ...

  5. 【Java面试题系列】:Java中final finally finalize的区别

    本篇为[Java面试题系列]第三篇,文中如有错误,欢迎指正. 第一篇链接:[Java面试题系列]:Java基础知识常见面试题汇总 第一篇 第二篇链接:[Java面试题系列]:Java基础知识常见面试题 ...

  6. Java中final,finally和finalize区别

    Day11_SHJavaTraing_4-18-2017 Java中final,finally和finalize区别 1.final—修饰符(关键字) ①final修饰类,表示该类不可被继承 ②fin ...

  7. 转 Java中final、finally、finalize的区别与用法

    Java中final.finally.finalize的区别与用法   1.简单区别:final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承.finally是异常处理语句结构 ...

  8. Java中 final static super this instanceof 关键字用法

    一.final关键字 final可以修饰变量.方法及类: 1.当定义一个final变量时,jvm会将其分配到常量池中,其所修饰的对象只能赋值一次,对基本类型来说是其值不可变,引用类型(包括作为函数形参 ...

  9. Java中final关键字修饰变量、方法、类的含义是什么

    Java中的关键字final修饰变量.方法.类分别表示什么含义? 先看一个简单的介绍 修饰对象 解释说明 备注 类 无子类,不可以被继承,更不可能被重写. final类中的方法默认是final的 方法 ...

随机推荐

  1. 14.1.3 Turning Off InnoDB 关掉InnoDB

    14.1.3 Turning Off InnoDB 关掉InnoDB: Oracle 推荐InnoDB 作为首选的存储引擎用于典型的数据库应用,从单用户的wikis到博客, 到高端应用把性能推到极限. ...

  2. mfc控件与其对应的对象的关联方法

    对话框的控件与其对应类的对象相关联:(两种方法) (1)      通过CWnd::DoDataExchange函数进行关联: 用VC++6.0的MFC ClassWizard中的Member Var ...

  3. 让动态创建的ActiveX控件响应Windows消息

    当我们通过 CWnd::CreateControl() 动态创建 ActiveX   控件时, Windows 消息并不会被发送给我 们的由   CWnd 派生得控件类.例如,即使我们为 WM_KIL ...

  4. Delphi接口的底层实现(接口在内存中仍然有其布局,它依附在对象的内存空间中,有汇编解释)——接口的内存结构图,简单清楚,深刻 good

    引言 接口是面向对象程序语言中一个很重要的元素,它被描述为一组服务的集合,对于客户端来说,我们关心的只是提供的服务,而不必关心服务是如何实现的:对于服务端的类来说,如果它想实现某种服务,实现与该服务相 ...

  5. 打印class文件的Java编译器内部的版本号

    当改变了jdk版本时,在编译java时,会遇到Unsupported major.minor version错误.错误信息如下 : Unsupported major.minor version 50 ...

  6. Cmpletepack coming~^.^

    昨天小小总结了01背包:01背包 不足之处还望多提意见~噶呜~ 今天来总结一下完全背包: 完全背包:    基本思路:类似于01背包,所不同的是每种物品有无限件.也就是从每种物品的角度考虑,策略已经不 ...

  7. VC调试技巧

    Visual C++ 的 C 运行时刻函数库标识模板0xCD    已经分配的数据(alloCated Data)0xDD    已经释放的数据(Deleted Data)0xFD    被保护的数据 ...

  8. [置顶] Cocos2d-x 实例源码分析之二 小实例的主框架

    这篇文章是分析第一个小实例ActionTest的源码.其实所有实例程序的结构都是一样的,只有特定方法里的代码不同,大的框架都是一样的.也就是说看完这篇文章你就可以自己开始分析其他源码了. 废话不多说, ...

  9. Centos 7 学习之静态IP设置

    原文链接:http://blog.csdn.net/johnnycode/article/details/40624403 本学习主要针对 Centos 7.0.1406 版本进行学习整理! 如果你使 ...

  10. web开发性能优化---用户体验篇

    怎样从技术角度怎样增强用户体验.都是非常多平台都在做的事情,依据个人实际经验碰到几种体验做下总结. 1.降低页面刷新白屏 适当使用ajax技术.改善刷新白屏现象. 2.信息提醒,邮件.站内信.短信在购 ...