从jdk1.0到今天,JAVA技术经过十余年的发展,技术上已经发生了巨大的变化.但final变量的定义从它
诞生那天起,就没有发生任何变化,也就是这十多年它就一直表示它原来的意思.
但遗憾的是,经过十多年仍然有90%的人没有理解它的真实含义,也没有一篇文章,包括我所见到的所有介绍
JAVA的书籍(包括TKJ)都没有说清楚,我相信肯定有些作者是理解的,但没有一个作者向读者说清楚.而中国网友
大多数人被一篇胡说八道的<<浅谈Java中final,finalized,finally>>的文章跑过马.(脸红一下:当初我也是).
final变量的定义本身并不复杂,就是变量一经初始化就不能再指向其它对象.在c++中它是一个const指针,而
不是指向const变量的指针,const指针的意思是说它只能一直指向初始化时的那个地址.但那个地址中对象本身
是可以修改的.而指向const变量的指针是说所指对象本身是不能修改的.
如:final StringBuffer sb = new StringBuffer("Axman");
sb = new StringBuffer("Sager");//错误,sb不能再指向其它对象.
sb.append(" was changed!"); //sb指向的地象本身可以修改.
先说final变量初始化:
很多文章都这么说:其初始化可以在两个地方,一是其定义处,二是在构造函数中,两者只能选其一。
胡说八道!
final变量可以在任何可以被始化的地方被始化,但只能被初始化一次.一旦被初始化后就不能再次赋
值(重新指向其它对象),作为成员变量一定要显式初始化,而作为临时变量则可以只定义不初始化(当然也不能引用)
即使是作为一个类中的成员变量,也还可以在初始化块中初始化,所以"其初始化可以在两个地方,一是其定义处,
二是在构造函数中,两者只能选其一"是错误的.
作为成员变量时,final字段可以设计不变类,是不变类的一个必要条件但不是一个充要条件.至少可以保证字段不
会以setXXX()这样的方式来改变.但无法保证字段本身不被修改(除非字段本身也是不变类);
对于方法参数的final变量:
对于方法参数的变量定义为final,90%以上的文章都说"当你在方法中不需要改变作为参数的对象变量时,明确使
用final进行声明,会防止你无意的修改而影响到调用方法外的变量。"
胡说八道!
我不知道这个修改是说重新赋值还是修改对象本身,但无论是哪种情况,上面的说法都是错误的.
如果是说重新赋值,那么:
public static void test(int[] x){
x = new int[]{1,2,3};
}
int[] out = new int[]{4,5,6};
test(out);
System.out.println(out[0]);
System.out.println(out[1]);
System.out.println(out[2]);
调用test(out);无论如何也不会影响到外面变量out.你加不加final根本没有意义.final只会强迫方法内
多声明一个变量名而已,即把x = new int[]{1,2,3};改成int y = new int[]{1,2,3}; 其它没有任何实际意义.
如果说是修改对象本身:
public static void test(final int[] x){
x[0] = 100;
}
int[] out = new int[]{4,5,6};
test(out);
System.out.println(out[0]);
难道你用final修饰就不可以修改了?所以说对于方法参数中final是为了不影响调用方法外的变量那是胡说八道的.
那我们到底为什么要对参数加上final?其实对方法参数加final和方法内变量加上final的作用是相同的,即为了将它们
传给内部类时保证调用的一致性:
abstract class ABSClass{
public abstract void m();
}
现在我们来看,如果我要实现一个在一个方法中匿名调用ABSClass.应该:
public static void test(final String s){
//或final String s = "axman";
ABSClass c = new ABSClass(){
public void m(){
int x = s.hashCode();
System.out.println(x);
}
};
//其它代码.
}
从代码上看,在一个方法内部定义的内部类的方法访问外部方法内局部变量或方法参数,是非常自然的事,但内部类编译的时候如何获取这个变量,因为内部类除了它的生命周期是在方法内部,其它的方面它就是一个普通类。那么它外面的那个局部变量或方法参数怎么被内部类访问?编译器在实现时实际上是这样的:
public static void test(final String s){
//或final String s = "axman";
class OuterClass$1 extends ABSClass{
private final String s;
public OuterClass$1(String s){
this.s = s;
}
public void m(){
int x = s.hashCode();
System.out.println(x);
}
};
ABSClass c = new OuterClass$1(s);
//其它代码.
}
即外部类的变量被作为构造方法的参数传给了内部类的私有成员.
假如没有final,那么:
public static void test(String s){
//或String s = "axman";
ABSClass c = new ABSClass(){
public void m(){
s = "other";
}
};
System.out.println(s);
}
就会编译成:
public static void test(String s){
//或String s = "axman";
class OuterClass$1 extends ABSClass{
private String s;
public OuterClass$1(String s){
this.s = s;
}
public void m(){
s = "other";
}
};
ABSClass c = new OuterClass$1 (s);
}
内部类的s重新指向"other"并不影响test的参数或外部定义的那个s.同理如果外部的s重新赋值内部类的s也不会跟着改变。
而你看到的
public static void test(String s){
//或String s = "axman";
ABSClass c = new ABSClass(){
public void m(){
s = "other";
}
};
System.out.println(s);
}
在语法上是一个s,在内部类中被改变了,但结果打印的出来的你认为是同一的s却还是原来的"axman",
你能接收这样的结果吗?
所以final从语法上约束了实际上两个不同变量的一致性(表现为同一变量).
转自:http://blog.csdn.net/axman/archive/2006/12/25/1460544.aspx
分享到:
相关推荐
UI框架对canvas进行分层 1.base为基础层,放基础界面,主游戏菜单、操作杆、小地图等; 2.main为主业务层,放全部业务界面,背包、榜单等 3.toast层,放吐司 4.loading层,放loading界面 使用方式: 1.在场景中挂上UIManager脚本,并在游戏启动时进行初始化,传入资源加载器 2.显示界面直接UIManager.ShowPanel<T>(),不需要其他操作 3.隐藏界面UIManager.ClosePanel()
IMG_1399.PNG
【毕业设计】java-springboot-vue教师工作量管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
python教程学习
【深圳来觅数据信息科技-2025研报】减产提价!多重因素影响,国内存储芯片逐步崛起.pdf
python学习资源
本协力服装厂服装生产管理系统设计目标是实现协力服装厂服装生产的信息化管理,提高管理效率,使得协力服装厂服装生产管理作规范化、科学化、高效化。 本文重点阐述了协力服装厂服装生产管理系统的开发过程,以实际运用为开发背景,基于Springboot框架,运用了Java编程语言和MYSQL数据库进行开发,充分保证系统的安全性和稳定性。本系统界面良好,操作简单方便,通过系统概述、系统分析、系统设计、数据库设计、系统测试这几个部分,详细的说明了系统的开发过程,最后并对整个开发过程进行了总结,实现了服装生产相关信息管理的重要功能。 本协力服装厂服装生产管理系统运行效果稳定,操作方便、快捷,界面友好,是一个功能全面、实用性好、安全性高,并具有良好的可扩展性、可维护性的服装生产管理平台。 关键词:服装生产管理,Java编程语言,Springboot框架,MYSQL数据库
网络编程,资源和大家上学的时候的差不多,tcp
vmware虚拟机安装教程
【毕业设计】java-springboot-vue教师人事档案管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
【毕业设计-java】springboot-vue会员制医疗预约服务管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
比赛前开源题目
UniApp开发一个简单的记事本应用文字教程
内容概要:本文档详细介绍了C#编程语言的基础知识和高级特性的相关内容。首先阐述了C#语言的特点和应用场景,涵盖其简单、安全及面向对象三大优点。接着讲述了准备工作的关键步骤,重点提及了开发工具Visual Studio的安装以及推荐的经典书籍和学习资源。文档深入解析了C#基础语法的各个要素,包括数据类型、变量与常量、运算符、控制结构,并结合代码实例强化理解。面向对象编程部分,文档讲解了类与对象的概念,以及继承、多态和封装的原则,并附带具体示例说明,以便读者更容易理解面向对象的理念。此外,文档对比了.NET Framework和.NET Core两大框架的区别和优势,并介绍了一些常用的类库,使开发者在不同平台环境下都可以顺利开发高质量的软件。最后一章提供了一些建议和资源推荐,如参与开源项目、加入技术社区等,为学习者的成长之路指明方向。 适合人群:希望初次接触C#编程的人士、希望通过系统学习达到掌握C#的初级开发者,亦适用于有一定C#经验,想巩固和提升面向对象思想及相关技术的专业技术人员。 使用场景及目标:该文章可以帮助初学者建立完整的C#编程基础框架,快速上手机编程,并引导他们深入了解面向
仅供资料参考,YeeCOM移讯通DTU连接OneNet平台MQTT说明使用手册。
python学习一些项目和资源
python学习资源
【毕业设计-java】springboot-vue家具销售电商平台实现源码(完整前后端+mysql+说明文档+LunW).zip
python学习教程
【毕业设计-java】springboot-vue健身房私人健身与教练预约管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip