内部类访问局部变量为什么要求局部变量添加final关键字

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

内部类访问局部变量为什么要求局部变量添加final关键字我们先来看一下JAVA对内部类的实现。JAVA编译器会把内部类编译为一个独立的class文件。其形式如下(类名为:外部类$内部类)。内部类在构造的时候,会被编译器自动传入外部类对象的一个引用,同时也会传入内部类访问的局部变量的引用,这也就解释了局部内部类对象为什么可以访问外部类的public成员变量public成员函数和成员函数内的局部变量了。由于这些工作是在编译时进行的,JAVA虚拟机并没有什么所谓的内部类的概念。在JAVA虚拟机看来,该内部类和外部类是两个普通的独立的class文件。我们知道,一个类的私有函数和成员变量是不能被其他类访问的。那么内部类又是如何访问外部类的私有成员变量和函数呢?我们假设外部类中有一个私有的int型的变量counter。我们想在内部类中访问它。其实在编译的时候,为了内部类可以访问外部类的私有变量,JAVA编译器还偷偷做了一些额外的工作。编译器除了上文提到的会生成一个内部类类,同时还会修改我们的外部类代码。其修改如下:1classTalkingClock{2//编译器自动添加的函数,用来访问私有成员变量counter3staticintaccess$0(TalkingClock);4//原有的函数5publicvoidstart();6//私有成员变量7privateintcounter8}可以看出,为了访问counter私有成员变量,编译器偷偷的为我们添加了一个access$0的静态函数,它接收一个外部类TalkingClock对象的引用,并返回外部类对象内的coutner的值。并且编译器会把我们在内部类中用到counter的地方都替换为TalkingClock.access$0(this$0)。总结:实际上java是将局部变量作为参数传给了局部内部类的构造函数,而将其作为内部类的成员属性封装在了类中。我们看到的内部类访问局部变量实际上只是访问了自己的成员属性而已,这和类的封装性是一致的。不能让类和类之间产生任何瓜葛,即使内部类和外部类之间也不可以。最后来看一下访问局部变量为什么要求局部变量添加final关键字。假设局部变量是一个基本数据类型。如果局部变量变量不被标注为final,那么就意味着我们可以随时修改它的值。由于,局部变量是在生成内部类对象的时候作为参数传进去的,所以内部类对象不知道局部变量已经被改了。假设我们在创建了外部类对象后修改了局部变量的值,而那么这时我们的内部类所看到的值还是之前通过构造函数传递进去的老值,这样就导致内部类和外部函数“认识”的不一致。所以final关键字的目的就是为了保证内部类和外部类的函数对变量“认识”的一致性。假设局部变量是一个对象的引用。如果局部变量变量不被标注为final,那么就意味着我们可以随时修改它的指向。由于,局部变量是在生成内部类对象的时候作为参数传进去的,所以内部类对象不知道引用的指向已经被改了。假设我们在创建了外部类对象后修改了这个引用的指向,而那么这时我们的内部类所看到的值还是之前通过构造函数传递进去的老值,也就是内部类的对象中的引用以为自己指向的还和局部变量修改之前所指的对象一样。这时候内部类这样就导致内部类和外部函数“认识”的不一致。所以final关键字的目的就是为了保证内部类和外部类的函数对变量“认识”的一致性。我们写代码的目的是在内部类中直接控制局部变量和引用,但我们就不高兴了,我在内部类中整半天以为是在操作外部变量,结果你给整个副本给我,我搞半天丫是整我自己的东西啊!要是java不这么整吧,由破坏了封装性。类的封装性咱们一定是要遵守的,不能破坏大局啊。但又要保证两个东西是一模一样的,包括对象和基本类型变量,那就使用final嘛,当传递普通变量的之前我把它变成一个常量。如果局部变量被final修饰,那么该局部变量就是常量。如果它是基本数据类型,它的值就不能被修改;如果它是一个引用,那么它所指的对象就不能再改变。从而内部类和外部类的函数对变量“认识”就一致啦。

1 / 2
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功