A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 Gaara33 于 2014-6-11 17:39 编辑
  1. class Outer
  2. {
  3.         int x=3;
  4.         void method(int a)
  5.         {
  6.                
  7.                 int y=10;//没有加final,也编译通过并运行了???
  8.                 //y++;//从内部类引用的本地变量必须是最终变量或实际上的最终变量。
  9.                 class Inner
  10.                 {
  11.                         void function()
  12.                         {
  13.                                 System.out.println(y);
  14.                                 System.out.println(a);
  15.                         }
  16.                 }
  17.                 new Inner().function();
  18.         }
  19. }

  20. class  InnerClassDemo3
  21. {
  22.         public static void main(String[] args)
  23.         {
  24.                 Outer out = new Outer();
  25.                 out.method(7);
  26.                 out.method(8);
  27.         }
  28. }
复制代码


在毕老师讲解的视频中,局部内部类,只能访问被final修饰的局部变量,但是我运行的时候,变量y没有加final也能运行,但是加上一句y++后就编译失败了,提示:从内部类引用的本地变量必须是最终变量或实际上的最终变量

我用的jdk1.8,win7,64位,这算是JDK1.8的新特性吗,不用加final.

评分

参与人数 1技术分 +1 收起 理由
李小然 + 1

查看全部评分

14 个回复

倒序浏览
你这里写的不对吧,类里边能嵌套类吗?
回复 使用道具 举报
我试了一下 必须加 final int y=10  我的jdk 是1.7
回复 使用道具 举报
跟你版本一样,一样编译通过了,但是放到eclipse 编译不能通过
回复 使用道具 举报
    猜测还是跟楼主的1.8 的JDK 有关系,我的1.7即使注销y++也未能编译通过,错误提示为变量y和a都必须声明为最终final变量,
  另:
       刚查了下跟1.8相关的新特性,中间提到一个lambda 项目,解决或部分解决了java匿名内部类中如下缺点:
   1. 语法相对复杂。
   2. 在调用内部类的上下文中,指引和this的指代容易混淆。
   3. 类加载和实例创建语法不可避免。
   4. 不能引用外部的非final对象。
   5. 不能抽象化控制流程

建议 楼主还是使用1.7 的sdk,新出的东西总会有各种不稳定性,

评分

参与人数 1技术分 +1 收起 理由
李小然 + 1

查看全部评分

回复 使用道具 举报 2 0
youngkay 发表于 2014-6-11 13:40
你这里写的不对吧,类里边能嵌套类吗?

恩恩 这是内部类
回复 使用道具 举报
确定编译可以通过?   我还以为是我理解错了     内部类绝对不能访问非final的成员变量
  因为内部类 也是类,他们实例化后存储在堆中;局部变量存储在栈中,所以一般情况而言内部类的声明周期长于局部变量。
试想一个活着的内部类去访问一个声明周期已经结束的局部变量~   
这不科学

QQ截图20140611162318.jpg (53.43 KB, 下载次数: 127)

编译失败

编译失败
回复 使用道具 举报
王春涛 发表于 2014-6-11 15:11
跟你版本一样,一样编译通过了,但是放到eclipse 编译不能通过

Eclipse内置的运行环境可能还没到1.8版本吧
回复 使用道具 举报
江夷 发表于 2014-6-11 15:47
猜测还是跟楼主的1.8 的JDK 有关系,我的1.7即使注销y++也未能编译通过,错误提示为变量y和a都必须声明 ...

嗯,我感觉也是版本问题
回复 使用道具 举报
附耳细说 发表于 2014-6-11 16:28
确定编译可以通过?   我还以为是我理解错了     内部类绝对不能访问非final的成员变量
  因为内部类 也是 ...

是的,确实编译通过了,但是加上那句y++之后,编译未通过,而且错误提示是这样 的

从内部类引用的本地变量必须是最终变量或实际上的最终变量

我想这个“或者实际上的最终变量”就是问题所在,JDK1.8可能出了新特性,省去可以写final,即使不写final也默认为最终变量了,所以才不可以y++,这是我的理解,我觉得你可以下载JDK1.8版本的,编译运行一下试试,我的确编译通过了。
回复 使用道具 举报
Gaara33 发表于 2014-6-11 16:38
嗯,我感觉也是版本问题

     建议还是用1.7的sdk,新版本sdk很多新特性,对于我们这些初学者来说可能会带来很多不必要的困惑,
回复 使用道具 举报
江夷 发表于 2014-6-11 16:56
建议还是用1.7的sdk,新版本sdk很多新特性,对于我们这些初学者来说可能会带来很多不必要的困惑, ...

嗯,我也赞同,有时候跟着视频练习,提示的错误信息会有一些很小的差别
回复 使用道具 举报
李俊贤 来自手机 初级黑马 2014-9-25 22:11:22
13#
为什么匿名内部类和局部内部类只能访问final变量 2012-8-30阅读1466 评论0  当一个方法中的匿名类或者局部内部类需要访问方法区域中的变量时,该变量参数必须定义为fina。  追究根本原因其实就是作用域中变量的生命周期导致的。  首先,内部类和外部类其实是处于同一个级别,内部类不会因为定义在方法中就会随着方法的执行完毕而跟随者被销毁。问题就来了,如果外部类的方法中的变量不定义final,那么当外部类方法执行完毕的时候,这个局部变量肯定也就被GC了,然而内部类的某个方法还没有执行完,这个时候他所引用的外部变量已经找不到了。如果定义为final,java会将这个变量复制一份作为成员变量内置于内部类中,这样的话,由于final所修饰的值始终无法改变,所以这个变量所指向的内存区域就不会变。说的比较糊涂,以下是高手A的 语录:  1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变量(形式参数或局部变量)是天经地义的.是很自然的 2)为什么JAVA中要加上一条限制:只能访问final型的局部变量? 3)JAVA语言的编译程序的设计者当然全实现:局部内部类能访问方法中的所有的局部变量(因为:从理论上这是很自然的要求),但是:编译技术是无法实现的或代价极高. 4)困难在何处?到底难在哪儿? 局部变量的生命周期与局部内部类的对象的生命周期的不一致性! 5)设方法f被调用,从而在它的调用栈中生成了变量i,此时产生了一个局部内部类对象inner_object,它访问了该局部变量i .当方法f()运行结束后,局部变量i就已死亡了,不存在了.但:局部内部类对象inner_object还可能一直存在(只能没有人再引用该对象时,它才会死亡),它不会随着方法f()运行结束死亡.这时:出现了一个"荒唐"结果:局部内部类对象inner_object要访问一个已不存在的局部变量i! 6)如何才能实现?当变量是final时,通过将final局部变量"复制"一份,复制品直接作为局部内部中的数据成员.这样:当局部内部类访问局部变量时,其实真正访问的是这个局部变量的"复制品"(即:这个复制品就代表了那个局部变量).因此:当运行栈中的真正的局部变量死亡时,局部内部类对象仍可以访问局部变量(其实访问的是"复制品"),给人的感觉:好像是局部变量的"生命期"延长了. 那么:核心的问题是:怎么才能使得:访问"复制品"与访问真正的原始的局部变量,其语义效果是一样的呢? 当变量是final时,若是基本数据类型,由于其值不变,因而:其复制品与原始的量是一样.语义效果相同.(若:不是final,就无法保证:复制品与原始变量保持一致了,因为:在方法中改的是原始变量,而局部内部类中改的是复制品)  当变量是final时,若是引用类型,由于其引用值不变(即:永远指向同一个对象),因而:其复制品与原始的引用变量一样,永远指向同一个对象(由于是final,从而保证:只能指向这个对象,再不能指向其它对象),达到:局部内部类中访问的复制品与方法代码中访问的原始对象,永远都是同一个即:语义效果是一样的.否则:当方法中改原始变量,而局部内部类中改复制品时,就无法保证:复制品与原始变量保持一致了(因此:它们原本就应该是同一个变量.)  一句话:这个规定是一种无可奈何.也说明:程序设计语言的设计是受到实现技术的限制的.这就是一例. 因为:我就看到不少人都持这种观点:设计与想法是最重要的,实现的技术是无关紧要的,只要你作出设计与规定,都能实现
回复 使用道具 举报
你的类写在方法里面了,就不叫内部类了
回复 使用道具 举报
确实 jdk1.8版本内部类成员变量不用final修饰也能访问
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马