内部使用final参数的原因

局部内部类(即:定义在方法中的内部类),访问方法中的局部变量

: 局部变量的生命周期与对象的生命周期的不一致性!方法在执行完方法的局部变量就消失,而内部类如果有引用还是存在的,那么将找不到变量。此时设计的做法是复制一份参数,为了保证复制的参数和方法的变量的一致,就需要保证其引用的对象不变,否则方法的局部变量的引用指向修改了,但是内部类却不知道

 1 public class Outer {
 2     public static void main(String[] args) {
 3         Outer outer = new Outer();
 4         Inner inner = outer.getInner("Inner", "gz");
 5         System.out.println(inner.getName());
 6     }
 7
 8     public Inner getInner(final String name, String city) {
 9            //final String name
10         return new Inner() { //或者定义一个内部线程,如果非final,引用指向改变了,内部类是无法知道的,因为编译时复制参数时参数被确定了引用指向
11             private String nameStr = name;
12
13             public String getName() {
14                 return nameStr;
15             }
16         };
17     }
18 }
19
20 interface Inner {
21     String getName();
22 } 

内部类并不是直接调用方法传进来的参数,而是内部类将传进来的参数通过自己的构造器备份到了自己的内部,自己内部的方法调用的实际是自己的属性而不是外部类方法的参数。

这样理解就很容易得出为什么要用final了,因为两者从外表看起来是同一个东西,实际上却不是这样,如果内部类改掉了这些参数的值也不可能影响到原参数,然而这样却失去了参数的一致性,因为从编程人员的角度来看他们是同一个东西,如果编程人员在程序设计的时候在内部类中改掉参数的值,但是外部调用的时候又发现值其实没有被改掉,这就让人非常的难以理解和接受,为了避免这种尴尬的问题存在,所以编译器设计人员把内部类能够使用的参数设定为必须是final来规避这种莫名其妙错误的存在。”

 (简单理解就是,拷贝引用,为了避免引用值发生改变,例如被外部类的方法修改等,而导致内部类得到的值不一致,于是用final来让该引用不可改变)

详细的解释是:

局部变量的生命周期与局部内部类的对象的生命周期的不一致性!

1)  设方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i .当方法f()运行结束后,局部变量i就已死亡了,不存在了.但:局部内部类对象inner_object还可能   一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.这时:出现了一个"荒唐"结果:局部内部类对象 inner_object要访问一个已不存在的局部变量i!

2)  如何才能实现?当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量 时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以 访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了.

那么:核心的问题是:怎么才能使得:访问"复制品"与访问真正的原始的局部变量,其语义效果是一样的呢? 
当变量是final时,若是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样.语义效果相同.(若:不是final,就无法保证:复制品与原始变量保持一致了,因为:在方法中改的是原始变量,而局部内部类中改的是复制品)

当 变量是final时,若是引用类型,由于其引用值不变(即:永远指向同一个对象),因而:其复制品与原始的引用变量一样,永远指向同一个对象(由于是 final,从而保证:只能指向这个对象,再不能指向其它对象),达到:局部内部类中访问的复制品与方法代码中访问的原始对象,永远都是同一个即:语义效 果是一样的.否则:当方法中改原始变量,而局部内部类中改复制品时,就无法保证:复制品与原始变量保持一致了(因此:它们原本就应该是同一个变量.)

时间: 2024-11-01 16:38:48

内部使用final参数的原因的相关文章

STM32F103使用内部Flash保存参数

在我们应用开发时,经常会有一些程序运行参数需要保存,如一些修正系数.这些数据的特点是:数量少而且不需要经常修改,但又不能定义为常量,因为每台设备可能不一样而且在以后还有修改的可能.将这类数据存在指定的位置,需要修改时直接修改存储位置的数值,需要使用时则直接读取,会是一种方便的做法.考虑到这些数据量比较少,使用专门的存储单元既不经济,也没有必要,而STM32F103内部的Flash容量较大,而且ST的库函数中还提供了基本的Flash操作函数,实现起来也比较方便. 以大容量产品STM32F103VE

微信的redirect_uri参数错误原因分析

我们可以根据微信的开发者文档  http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 网页授权获取用户验证这一章来排除错误原因. 如果确定appid等参数值没有出错,那么很大可能就是你的微信公众号后台的网页授权网址没有填写或者填写的不正确. 1.在微信公众号请求用户网页授权之前,开发者需要先到公众平台官网中的开发者中心页配置授权回调域名.请注意,这里填写的是域名(是一个字符串),而不是URL,因此请勿加http

Express post请求无法解析参数的原因

router.post('/', function(req, res) { console.log(req.body); console.log(req.body.name); console.log(req.body.tel); res.send("ok"); }); // 下面是log {} undefined undefined 原因:因为post的是一个raw的字符串,Express默认只支持json与x-www-form-urlencoded 解决方法:使用json对象与后台

ajax 内部值 外部调用不了原因

var id=‘123’; $.ajax({ url:’http://www.xxx.com/ajax', type:'post', dataType: "json", data:{wurl:w_url,murl:m_url}, async : turn, error:function(){ }, success:function(data){ var id= data[‘id’]; console.log(id) // 这里出来的是100 } }) console.log(id);

微信开发出现 redirect-uri参数错误原因是设置回调页面域名不要加HTTP://

OAuth2.0 网页授权设置,回调页面域名不要加HTTP:// NND  微信的研发,你程序处理下很麻烦吗?给个提示很麻烦吗?让我查了1个多小时. 版权声明:本文为博主原创文章,未经博主允许不得转载.

Oracle数据库错误消息

Oracle数据库错误消息 导出错误消息 l EXP-00000导出终止失败 原因:导出时产生Oracle错误. 操作:检查相应的Oracle错误消息. l EXP-00001数据域被截断 - 列长度=数字,缓冲区大小=数字,实际大小=数字 原因:数据缓冲区中列不适合. 操作:记录错误参数和消息,作为输出内部错误发送到Oracle Support Services(如果一个表不能完全导出,则导出不能继续). l EXP-00002写导出文件错误 原因:不能导入导出文件,可能由设备错误引起,通常伴

ORACLE错误1033出现和ORA-00600错误解决办法

非法关机以后,Oracle数据经常出现这个错误: EXP-00056:ORACLE错误1033出现 ORA-01033:ORACLE initialization or shutdown in progress 用户: 口令: 这个显然是数据库没有办法启动,但是数据库服务还是可以启动,但程序无法连接数据库. 首选找问题要看看数据库BDUMP目录下的ALERT文件具体报什么错误 你看到最后几行会有 报错ORA-00600: 内部错误代码,参数: [kcratr1_lostwrt], [], [],

为什么匿名内部类参数必须为final类型(转载)

为什么匿名内部类参数必须为final类型转自于:http://feiyeguohai.iteye.com/blog/1500108 1)  从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变量(形式参数或局部变量)是天经地义的.是很自然的 2)  为什么JAVA中要加上一条限制:只能访问final型的局部变量? 3)  JAVA语言的编译程序的设计者当然全实现:局部内部类能访问方法中的所有的局部变量

JAVA方法中的参数用final来修饰的效果

很多人都说在JAVA中用final来修饰方法参数的原因是防止方法参数在调用时被篡改,其实也就是这个原因,但理解起来可能会有歧义,我们需要注意的是,在final修饰的方法参数中,如果修饰的是基本类型,那么在这个方法的内部,基本类型的值是不能够改变的,但是如果修饰的是引用类型的变量,那么就需要注意了,引用类型变量所指的引用是不能够改变的,但是引用类型变量的值是可以改变的. 如下面的代码: package com.jd.test; public class Test{ public static vo