`
javaG
  • 浏览: 554877 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

再说final变量

阅读更多

从jdk1.0到今天,JAVA技术经过十余年的发展,技术上已经发生了巨大的变化.但final变量的定义从它
诞生那天起,就没有发生任何变化,也就是这十多年它就一直表示它原来的意思.

但遗憾的是,经过十多年仍然有90%的人没有理解它的真实含义,也没有一篇文章,包括我所见到的所有介绍
JAVA的书籍(包括TKJ)都没有说清楚,我相信肯定有些作者是理解的,但没有一个作者向读者说清楚.而中国网友
大多数人被一篇胡说八道的<<浅谈Java中final,finalized,finally>>的文章跑过马.(脸红一下:当初我也是).

final变量的定义本身并不复杂,就是变量一经初始化就不能再指向其它对象.在c++中它是一个const指针,而
不是指向const变量的指针,const指针的意思是说它只能一直指向初始化时的那个地址.但那个地址中对象本身
是可以修改的.而指向const变量的指针是说所指对象本身是不能修改的.

如:final StringBuffer sb = new StringBuffer("Axman");
sb = new StringBuffer("Sager");//错误,sb不能再指向其它对象.
sb.append(" was changed!"); //sb指向的地象本身可以修改.

先说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(final String s){
     //或final String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
      int x = s.hashCode();

      System.out.println(x);

   }
  };
  //其它代码.
 }
 实际上这段代码被编译成:
  public static void test(final String s){
     //或final String s = "axman";
  ABSClass c = new ABSClass(s){
   private final String s;
   public ABSClass(String s){
 this.s = s;  
   }
   public void m(){
      int x = s.hashCode();

      System.out.println(x);

   }
  };
  //其它代码.
 }
即外部类的变量被作为构造方法的参数传给了内部类的私有成员.
假如没有final,那么:
 public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
     s = "other";
   }
  };
  System.out.println(s);
 }
 就会编译成:
  public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(s){
   private final String s;
   public ABSClass(String s){
 this.s = s;  
   }
   public void m(){
  s = "other";
   }
  };
  System.out.println(s);
 }
 内部类的s重新指向"other"并不影响test的参数或外部定义的那个s.而你看到的
  public static void test(String s){
     //或String s = "axman";
  ABSClass c = new ABSClass(){
   public void m(){
     s = "other";
   }
  };
  System.out.println(s);
 }
 在语法上是一个s,在内部类中被改变了,但结果打印的出来的你认为是同一的s却还是原来的"axman",
 你能接收这样的结果吗?
 所以final从语法上约束了两个不同变量的一致性.

分享到:
评论

相关推荐

    java final变量详解

    Java final 变量详解 Java 中的 final 变量是指不能被改变的变量,它有三个方面的作用:修饰变量、修饰方法和修饰类。在 Java 中,final 变量是一种常量,它只能被赋值一次,赋值后值不再改变。 final 变量的使用...

    局部变量用final的讨论

    标题中的“局部变量用final”的讨论主要聚焦于Java编程语言中的一个特性,即使用`final`关键字修饰局部变量。在Java中,`final`关键字有多种用途,包括但不限于定义不可变对象、创建常量以及限制变量的赋值次数。在...

    final变量.

    `final`变量确保其值在赋值后不会被修改,从而提供了数据的安全性和一致性。这在多个方面都有其优势,包括效率、设计约束以及代码优化。 1. **效率问题**: `final`关键字有时用于效率考虑,特别是当一个方法被...

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

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

    Eclipse设置保存时自动给变量加final

    标题“Eclipse设置保存时自动给变量加final”涉及到的是在Eclipse集成开发环境中(IDE)进行代码风格和规范配置的技巧。Eclipse是一个广泛使用的Java IDE,它提供了丰富的功能和自定义选项,以满足不同开发者的需求...

    深入理解final变量的初始化

    在Java编程语言中,`final`关键字用于声明不可变的变量。这些变量一旦被初始化,就不能再更改其值。深入理解`final`变量的初始化至关重要,因为它涉及到程序的正确性和内存管理。以下是对`final`变量初始化的详细...

    final类,方法,变量

    本篇文章将深入探讨`final`关键字在类、方法和变量中的应用,以及它们对程序设计的影响。 首先,让我们了解`final`关键字在类中的使用。当一个类被声明为`final`时,这意味着它不能被继承。这意味着这个类是封闭的...

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

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

    java_中的_final_变量[文].pdf

    在Java编程语言中,`final`关键字扮演着重要的角色,它用于声明不可变的变量、方法和类。理解`final`的关键在于其不可变性,这有助于提高程序的效率、稳定性和设计规范。 首先,`final`变量表示常量,一旦赋值后就...

    final和static用法详解JAVA

    final 修饰的变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。final 变量定义的时候,可以先声明,而不给初值,这中变量也称为 final 空白,无论什么情况,编译器都确保空白 final 在使用之前...

    Java中final的深度剖析

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

    JavaSE之final关键字与成员变量的类型

    【JavaSE之final关键字与成员变量的类型】 在Java编程语言中,`final`关键字扮演着重要的角色,它表示“最终”或“不可改变”的特性。对于初学者来说,理解`final`的关键字用法是掌握JavaSE基础的重要一步。本篇...

    ClassFinal-java class文件安全加密工具

    2. **混淆**:混淆是另一种保护代码的方法,它通过重命名类、方法和变量,以及改变控制流结构,使得反编译后的代码变得难以理解和分析。ClassFinal可能包含多种混淆策略,如名称混淆、控制流混淆、字符串加密等。 3...

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

    ### Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释 #### 背景介绍 在Java编程语言中,局部内部类(Local Inner Class)是一种特殊的内部类形式,它被定义在某个方法或构造器的内部。...

    day11 05 final关键字用于修饰成员变量

    day11_05_final关键字用于修饰成员变量

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

    在本文中,我们将深入探讨`final`在变量、参数、方法和类中的应用及其作用。 **1. `final`关键字用于变量** - **final基本类型变量**:当`final`用于基本类型的变量时,它被视为常量,一旦赋值后就不能更改。尝试...

    Java中final变量使用总结

    当我们在声明变量时使用`final`,我们确保该变量的值一旦被赋值,就不能再次改变。这使得`final`变量成为常量,它们在程序执行期间保持不变。 1. **final变量的声明** - 对于基本类型变量,如`int`、`double`等,...

    Java关键字final、static使用总结

    final 变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。 4、final 参数 final 参数可以读取使用该参数,但是无法改变该参数的值。 二、static 关键字 static 关键字可以用来修饰成员变量和...

    javafinal和static总结.docx

    final 变量是值一旦给定就无法改变的变量,final 变量有三种:静态变量、实例变量和局部变量,分别表示三种类型的常量。 例如: `private final String S = "final 实例变量 S";` final 变量定义的时候,可以先...

Global site tag (gtag.js) - Google Analytics