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

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 变量是一种常量,它只能被赋值一次,赋值后值不再改变。 final 变量的使用...

    Java中final的深度剖析

    在Java 8引入的lambda表达式中,final变量可以作为lambda的捕获变量,这保证了lambda表达式的封闭性,即它们不能修改外部的非final变量。 总结来说,final关键字在Java编程中扮演了多种角色,从确保常量的不变性,...

    java成员变量覆盖问题

    ### Java成员变量覆盖问题详解 在Java编程语言中,成员变量是指定义在类中的变量,它们可以在类的方法、构造器或类的其他成员方法中访问和操作。成员变量的覆盖(有时会被误认为是“重写”)是理解Java继承机制的...

    Java final关键字

    在Java编程语言中,`final`关键字扮演着一个至关重要的角色,它被用来声明一个变量、方法或类为不可变的。在这个学习demo中,我们将深入理解`final`关键字的各种用法及其背后的原理。 首先,`final`关键字用于变量...

    局部变量用final的讨论

    这是因为内部类可以访问外部类的final或effectively final变量,而这些变量被视为常量。 3. **代码优化**:JVM可能会对`final`局部变量进行优化,如逃逸分析,将它们存储在栈上而不是堆上,提高运行效率。 4. **...

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

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

    【Java编程教程】详解Java final 关键字.pdf

    如果`final`变量在声明时没有赋值,那么它被称为“空白最终变量”或“未初始化的final变量”。这样的变量必须在构造函数中进行初始化,或者对于静态的`final`变量,可以在静态初始化块中初始化。例如: ```java ...

    java 常量与变量

    在Java编程语言中,常量和变量是两个基础且重要的概念。它们是程序中存储数据的容器,理解它们的性质和用法对于编写高效的代码至关重要。 ### 常量 常量是固定不变的值,一旦被定义就不能再更改。在Java中,我们...

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

    Java中的`final`关键字在编程中扮演着至关重要的角色,它用于确保代码的不可变性和确定性。在本文中,我们将深入探讨`final`在变量、参数、方法和类中的应用及其作用。 **1. `final`关键字用于变量** - **final...

    java中final和static的区别

    final 关键字在 Java 中有多种用法,包括修饰变量、方法、类等。下面是 final 关键字的各种用法: 1. final 修饰变量:表示该变量一旦被初始化,程序无法修改变量的值,该变量变成了一个常量。注意,系统不会默认为...

    javafinal和static总结.docx

    final 关键字在 Java 中有多种用途,包括修饰类、方法和变量。 1. final 类 final 类是无法被继承的,final 类中的方法默认是 final 的,final 类不能被继承,没有子类。例如: `public final class MyClass { .....

    Java中的final关键字

    1. **final变量** - `final`修饰的局部变量一旦初始化后,就不能再改变其值。这有助于防止意外修改,增加代码的可预测性和安全性。 - 类级(静态)常量通常也用`final`修饰,例如`public static final`,这样的...

    java 变量、关键字

    ### Java 变量与关键字详解 #### 一、关键字(Keywords) **1. 关键字概述** Java的关键字对编译器具有特殊的意义,它们用来表示特定的数据类型或程序结构等。关键字不能用作变量名、方法名、类名或包名。 **2. ...

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

    Java中的`final`和`static`关键字是编程中非常重要的两个修饰符,它们分别用于不同的场景,以确保代码的稳定性和高效性。 首先,`final`关键字主要用于表示不可变性。它可以用来修饰类、方法和变量。对于类,如果一...

    深入理解Java中的final关键字_动力节点Java学院整理

    Java 中的 `final` 关键字是一个至关重要的概念,它被用来声明类、方法和变量,以确保它们在程序执行过程中不可更改。深入理解 `final` 关键字可以帮助开发者写出更加安全、高效的代码。 首先,`final` 关键字可以...

    Java关键字final、static使用总结

    在 Java 编程语言中,final 和 static 是两个非常重要的关键字,它们可以用来修饰类、方法、变量等,了解它们的使用方法和限制非常重要。本文将详细总结 final 和 static 的使用方法和限制。 一、final 关键字 ...

    java 常量 变量 详细实例

    在Java编程语言中,常量和变量是两个基础且至关重要的概念。它们是程序中存储数据的容器,理解和熟练运用它们对于编写高质量的Java代码至关重要。 **常量**在Java中指的是不可更改的值。一旦定义,其值就不能再被...

    java常量变量表达式

    在Java中,常量变量表达式是编程时常见的概念,它们涉及到如何定义、使用和管理不可变的数据。 1. 常量变量: 在Java中,常量是不可更改的值,通常使用关键字`final`来声明。例如: ```java final int MAX_SIZE = ...

    [Java4Android 04_Java的变量

    了解和掌握Java的变量是编程的基础,对于初学者来说至关重要。在Java中,变量是用来存储数据的容器,它有特定的数据类型,可以是基本类型或者引用类型。 1. 基本数据类型: Java的基本数据类型分为两大类:原始...

    Java中变量的使用规则共2页.pdf.zip

    8. **final变量**:final变量一旦赋值就不能再改变,可以用来创建常量或者保证对象引用的不可变性。 9. **变量的默认值**:未初始化的局部变量和实例变量会有默认值,例如int类型的默认值是0,boolean类型的默认值...

Global site tag (gtag.js) - Google Analytics