`

Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释

 
阅读更多

标题有点长,可能有点语病,先别管那么多!
首先看下面的这段代码:

public class LocalInnerClassTest{
      public static void main(String[] args){
         Outer obj=new Outer();          //生成一个外部类对象
         SuperInner si=obj.outer();        //调用外部类中的outer()方法,返回一个SuperInner类型对象赋值给si
        si.m1();             //调用被覆盖的方法m1(),输出:Inner's m1() 20
     }
}

/**
*定义一个接口SuperInner,内部定义一个抽象方法m1(),无返回类型
*/
interface SuperInner{
     public void m1();
}

/**
*定义一个类Outer,内部只定义一个方法outer(),返回类型为SuperInner
*/
class Outer{
     public SuperInner outer(){
        int a=10;                   //方法中定义一个局部变量a,并赋值为10
        final int b=20;          //再定义一个final局部变量b,初始化为20

        class Inner implements SuperInner{              //在outer()方法中定义一个局部内部类Inner,实现接口SuperInner
           public void m1(){    //类中只有一个覆盖接口SuperInner的方法m1()
              System.out.println("Inner's m1()"+a);    //编译报错
              System.out.println("Inner's m1() "+b);    //编译通过,输出:Inner's m1() 20
           }
        }
        return new Inner();
     }
}

 我们先从主方法开始看代码的执行顺序,先生成一个Outer类对象obj,obj调用本类 中方法outer();程序开始跳到outer()方法内执行程序语句,先后生成局部变量a和b,再定义一个局部内部类Inner,返回一个 SuperInner类型的对象。将返回的SuperInner类型对象地址传给SuperInner类型对象si。si再调用m1()方法,因为已经在 局部内部类中覆盖了接口中的m1()方法,所以将调用局部内部类中的m1()方法,程序跳到局部内部类中m1()方法内执行程序语句,先输出一段字符串和 a,结果编译报错,先 将这条程序语句隐藏,执行下面的语句,你会发现编译通过而且输出Inner's m1() 20!

为 什么会这样呢?大家都知道局部变量仅仅在一个范围内有效,在方法调用完就被内存释放,在Outer类对象obj调用outer()方法时,a和b才产生, 调用结束后被内存释放,那么b这个值也就不复存在了,为什么还会输出20呢?难道局部变量被final修饰就不会被内存释放而保留?

其 实有部分操作对于程序员是透明的,那是JAVA语言开发者的小把戏,在定义a和b 时JVM(JAVA虚拟机)做了程序员看不到的操作,他将b拷贝了一份给局部内部类,也就是说JVM在局部内部类中定义了一个final int b=20;这个操作程序员是不知道的!当调用m1()方法时输出的20并不是原来outer()方法中定义的b,而仅仅是JVM拷贝的一个副本。那么为什 么a没被打印出呢?那是因为JVM并没有拷贝它,因为没有final修饰,说明它可以被修改,如果把a 改为 a++ ,此时JVM就不知道拷贝a还是a++了,所以对于无final修饰的局部变量JVM是不会拷贝传给局部内部类的,自然无法打输出!

分享到:
评论

相关推荐

    Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释.doc

    Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释.doc

    【Java语言基础】final关键字

    【Java语言基础】final关键字 修饰词:final 最终的最后的 final关键字可用于修饰符,变量和方法...final修饰局部变量 可以在定义时指定默认值,则后面代码中不能再对改变量赋值。 如果在定义时没有指定默认值,则可以

    Java岗面试核心MCA版

    一小块区域 成员变量:方法外部,类内部定义的变量 局部变量:类的方法中的变量。 成员变量和局部 变量的区别 作用域 成员变量:针对整个类有效。 局部变量:只在某个范围内有效。(一般指的就是方法,语句体内)

    【05-面向对象(下)】

    •使用final修饰局部变量时既可以在定义时指定默认值,也可以不指定默认值。 •给局部变量赋初始值,只能一次,不能重复。 final修饰基本类型和引用类型 •当使用final修饰基本数据类型时,不能对其重新...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

    子类从它先辈类那里继承了代码和数据,这样,它就可以执行先辈类的功能和访问先辈 类的数据。一个纯面向对象程序设计的语言将具有严格的继承性。 通过对象、类,我们实现了封装,通过子类我们可以实现继承。例如,...

    JAVA入门1.2.3:一个老鸟的JAVA学习心得 PART1(共3个)

    11.4.6 使用final修饰成员变量 325 11.4.7 静态成员变量 326 11.4.8 局部变量的修饰符 326 11.4.9 当final遇到引用类型成员变量 327 11.5 小结:修饰符作用大 328 11.6 习题 330 第12章 接口 331 教学视频:...

    Java入门1·2·3:一个老鸟的Java学习心得.PART3(共3个)

    11.4.6 使用final修饰成员变量 325 11.4.7 静态成员变量 326 11.4.8 局部变量的修饰符 326 11.4.9 当final遇到引用类型成员变量 327 11.5 小结:修饰符作用大 328 11.6 习题 330 第12章 接口 331 教学视频:...

    JAVA 面向对象程序设计第4章 抽象类和接口.pptx

    第4章 抽象类与接口;回顾;本章内容;4.1 抽象类;4.1 抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.1 抽象方法和抽象类;4.1.2 ...

    21天学通Java-由浅入深

    240 12.2.1 创建局部内部类 240 12.2.2 在局部内部类中访问外部类成员变量 240 12.2.3 在局部内部类中访问外部类的局部变量 241 12.2.4 静态方法中的局部内部类 243 12.3 静态内部类 244 12.3.1 创建静态内部类 244 ...

    java 面试题 总结

    派生类可以从它的基类那里继承方法和实例变量,并且类可以修改或增加新的方法使之更适合特殊的需要。 3.封装: 封装是把过程和数据包围起来,对数据的访问只能通过已定义的界面。面向对象计算始于这个基本概念,即...

    【04-面向对象(上)】

    – 方法中的修饰符可以是public ,protected,private,static,final,abstract,其中访问控制符只能出现一 个,abstract ,final 只能出现其一. –返回值类型可以是基本类型和引用类型,如果无返回值,要用void 来声明 ...

    疯狂JAVA讲义

    学生提问:既然内部类是外部类的成员,是否可以为外部类定义子类,在子类中再定义一个内部类来重写其父类中的内部类? 211 6.7.4 局部内部类 211 6.7.5 匿名内部类 212 6.7.6 闭包(Closure)和回调 215 6.8 ...

    java基础案例与开发详解案例源码全

    6.6 final修饰符171 6.7 abstract修饰符172 6.8 接口173 6.8.1 接口的定义及实现174 6.8.2 接口中的常量174 6.8.3 接口的多重实现174 6.9 本章练习175 第7章 7.1 面向对象的分析与设计简介180 7.1.1 类的设计建议180...

    JavaLearnSummary:java学习总结

    JavaLearnSummary java学习总结 JAVA基础知识 1. final关键字 Ø 修饰类,代表该类不能被继承;final类比普通类有更高的效率 ...因此使用final修饰局部变量时,既可以在定义时指定默认值(后面的代码不能再对变

    java面试宝典

    42、一个“.java”源文件中是否可以包含多个类(不是内部类)?有什么限制? 12 43、说出一些常用的类,包,接口,请各举5 个。 12 44、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类?是否可以...

    javaSE代码实例

    15.2.2 局部变量与局部内部类 329 15.2.3 静态方法中的局部内部类 331 15.3 静态内部类 332 15.3.1 语法规则 332 15.3.2 创建静态内部类的对象 332 15.3.3 静态/非静态内部类的区别 333 15.4 匿名内部...

    北邮高级语言程序设计(基于Java)第三次阶段作业.docx

    子类只能重载父类的方法,而不能覆盖 子类不能定义和父类名同名同形参的方法,否则,系统将不知道使用哪种方法 重载就是一个类中有多个同名但有不同形参和方法体的方法 知识点: 第三单元过关自测 学生答案: [D;...

    突破程序员基本功的16课.part2

    2.4.4 内部类中的局部变量 2.5 小结 第3课 常见Java集合的实现细节 3.1 Set和Map 3.1.1 Set和Map的关系 3.1.2 HashMap和HashSet 3.1.3 TreeMap和TreeSet 3.2 Map和List 3.2.1 Map的values()方法 3.2.2 ...

Global site tag (gtag.js) - Google Analytics