`
xm_king
  • 浏览: 392498 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Spring技术内幕读书笔...
浏览量:15348
社区版块
存档分类
最新评论

java final变量(转)

    博客分类:
  • JAVA
阅读更多

      final变量定义: 变量一经初始化就不能指向其它对象。指向的存储地址不可修改,但指向的对象本身是可以修改的。
       先说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(String s){
     //或String s = "";
  ABSClass c = new ABSClass(){
   public void m(){
      int x = s.hashCode();

      System.out.println(x);

   }
  };
  //其它代码.
} 

 注意这里,一般而言,回调方法基本上是在其它线程中调用的.如果我们在上面的

     ABSClass c = new ABSClass(){
   public void m(){
       int x = s.hashCode();
       System.out.println(x);
   }
  }; 

 

       后面直接调用c.m();应该是没有意义的.但这不重要,重要的是只要有可能是在其它线程中调用,那我们就必须为s保存引用句柄。
         我们先来看GC工作原理,JVM中每个进程都会有多个根,每个static变量,方法参数,局部变量,当然这都是指引用类型. 基础类型是不能作为根的,根其实就是一个存储地址. GC在工作时先从根开始遍历它引用的对象并标记它们,如此递归到最末梢,所有根都遍历后,没有被标记到的对象说明没 有被引用,那么就是可以被回收的对象(有些对象有finalized方法,虽然没有引用,但JVM中有一个专门的队列引用它们直到finalized方法被执行后才从该队列中移除成为真正没有引用的对象,可以回收,这个与本主题讨论的无关,包括代的划分等以后再说明).这看起来很好.
       但是在内部类的回调方法中,s既不可能是静态变量,也不是方法中的临时变量,也不是方法参数,它不可能作为根,在内部类
中也没有变量引用它,它的根在内部类外部的那个方法中,如果这时外面变量重指向其它对象,则这个对象就失去了引用, 可能被回收,而由于内部类回调方法大多数在其它线程中执行,可能还要在回收后还会继续访问它.这将是什么结果?
       匿名内部类把需要访问的外部变量作为一个隐藏的字段,这样得到了一个变量的引用拷贝
,使用final修饰符不仅会保持对象不会改变,而且编译器还会持续维护这个对象在回调方法中的生命周期。所以这才是final 变量和final参数的根本意义。

分享到:
评论

相关推荐

    java final变量详解

    java final变量详解 java final变量详解 java final变量详解 java final变量详解

    深入理解Java final变量的内存模型

     在构造函数内对一个 final 域的写,与随后把这个构造对象的引用赋值给一个变量,这两个操作之间不能重排序  初次读一个包含 final 域的对象的引用,与随后初次读这个 final 域,这两个操作之间不能重排序  举...

    Java中final作用于变量、参数、方法及类该如何处理

    Java中的final关键字非常重要,它可以应用于类、方法以及变量,下面这篇文章主要给大家介绍了关于Java中final作用于变量、参数、方法及类该如何处理的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考...

    final修饰成员变量和局部变量.md

    本文章是关于final部分知识所作的自我总结,内容为final对成员变量和局部变量修饰的简要解答,除了对自我java学习的一个小结,也希望能够帮助到在java路上对该内容疑惑的同行

    Java中final变量使用总结

    主要介绍了Java中final变量使用总结,final关键字可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值,通常final定义的变量为常量,需要的朋友可以参考下

    Java零基础-final关键字.md

    在阅读过程中,尝试编写简单的Java程序,体验final关键字的作用,并观察final变量和final方法的特性。 建议通过阅读相关的Java教材或搜索资料,进一步了解与final关键字相关的高级主题,如不可变类和Enum枚举等内容...

    java中final关键字和static关键字详细用法

    根据程序上下文环境,Java关键字final有“这是无法改变的”或者“终态的”含义,它可以修饰非抽象类、非抽象类成员方法和变量。你可能出于两种理解而需要阻止改变:设计或效率。

    Java并发--final关键字.docx

    在Java中变量可以分为成员变量和局部变量 成员变量 通常每个类中成员变量可以分为 类变量(static修饰的变量) 以及 实例变量 针对这两种类型的变量...当final变量未初始化时系统不会进行隐式初始化,会出现报错。

    深入理解final变量的初始化

    本篇文章是对final变量的初始化进行了详细的分析介绍,需要的朋友参考下

    【Java语言基础】final关键字

    【Java语言基础】final关键字 修饰词:final 最终的最后的 final关键字可用于修饰符,变量和方法,用于表示它修饰的类,方法和方法不可改变。 final 最终的最后的 final修饰变量时,表示该变量一旦获得了初始值之后...

    java_中的_final_变量[文].pdf

    java_中的_final_变量[文].pdf

    java为什么匿名内部类的参数引用时final?final局部变量的生命周期

    在知乎上看到了一篇帖子 在这个问题下面大家已经吵得不可开交了,看了很多篇文章,被误导进了很多的坑,发现只有下面两篇文章是写的最好的,解释的很清楚,我把两篇文章简单的总结了一下: ...1.问题的引出 ...

    Java SE编程入门教程 java static final(共24页).pptx

    Java SE编程入门教程 java static final(共24页).pptx Java SE编程入门教程 java this和super(共10页).pptx Java SE编程入门教程 java 常用API(共22页).pptx Java SE编程入门教程 javaGUI编程快速入门(1)(共...

    计算机后端-Java-Java核心基础-第15章 面向对象07 26. final修饰局部变量.avi

    计算机后端-Java-Java核心基础-第15章 面向对象07 26. final修饰局部变量.avi

    Java SE编程入门教程 java入门以及变量debug(共63页).pptx

    Java SE编程入门教程 java static final(共24页).pptx Java SE编程入门教程 java this和super(共10页).pptx Java SE编程入门教程 java 常用API(共22页).pptx Java SE编程入门教程 javaGUI编程快速入门(1)(共...

    动力节点老杜Java基础入门视频教程——final修饰局部变量

    012-JavaSE进阶-final修饰局部变量

    Java反射如何修改private final成员变量值

    主要介绍了Java反射如何修改private final成员变量值,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    举例讲解Java中final关键字的用法

    Java中的final关键字可以被用来修饰变量、方法和类等,意味着终结、不可改变,下面我们就来举例讲解Java中final关键字的用法:

    Java中final关键字详解

     在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。下面就从这三个方面来了解一下final关键字的基本用法。  1.修饰类  当用final修饰一个类时,表明这个类不能被继承。也就是说,...

    Java中的final关键字详解及实例

    Java中的final关键字 1、修饰类的成员变量 这是final的主要用途之一,和C/C++的const,即该成员被修饰为常量,意味着不可修改。   上面的代码对age进行初始化后就不可再次赋值,否则编译时会报类似上图的错误。 ...

Global site tag (gtag.js) - Google Analytics