Java之final修饰变量

原创 2016年05月31日 15:25:20


final修饰的实例变量

被final修饰的实例变量必须显示指定初始值,而且只能在如下3个位置指定初始值:
1.定义final实例变量时指定初始值;
2.在非静态初始化块中为final实例变量指定初始值
3.在构造器中为final实例变量指定初始值
对于普通实例变量,Java程序可以对它执行默认的初始化,也就是将实力变量的值指定为默认的初始值0或null,但对于final实例变量,则必须由程序员显示指定初始值。
final实例变量必须显示地被赋初始值,而且本质上final实例变量只能在构造器中被赋初始值。在定义final实例变量时指定初始值,和在初始化块中为final实例变量指定初始值本质上是一样的。除此之外,final实例变量将不能被再次赋值。

final修饰的类变量

对于final类变量而言,同样必须显示指定初始值,而且final类变量只能在2个地方指定初始值:
定义final类变量时指定初始值;
在静态初始化块中为final类变量指定初始值;
这两种方式都会被抽取到静态初始化块中赋初始值。定义final类变量时指定初始值和在静态初始化块中为final类变量指定初始值,本质是一样的。除此之外final类变量将不能被再次赋值。

final修饰局部变量

final修饰的局部变量一样需要被显式地赋初始值,因为Java本来就要求局部变量必须被显式地赋初始值。与普通变量不同的是,final修饰的局部变量被赋初始值之后,将不能再被重新赋值。

final修饰符的第一简单的功能就是一旦被赋初始值,将不可改变。
final的另一个简单的功能就是在定义了该final类变量时指定了初始值,且该初始值可以在编译时就被确定下来,系统将不会在静态初始化块中对该类变量赋初始值,而将是在类定义中直接使用该初始化值代替该final变量。

对于一个使用final修饰的变量而言,如果定义该final变量时就指定初始值,而且这个初始值可以在编译时就确定下来,那么这个final变量将不再是一个变量,系统会将其变成“宏变量”处理。所有出现该变量的地方,系统将直接把它当成对应的值处理。

执行“宏替换”的变量

对于一个final变量,不管它是类变量、实例变量还是局部变量,定义了该变量时使用了final修饰符修饰,并在定义该final类变量时指定了初始值,而且该初始值可以在编译时就被确定下来,那么这个final变量本质上已经不再是变量,而是想当于一个直接的变量。
final修饰符的一个重要用途就是定义“宏变量“,当定义final变量时就为该变量指定了初始值,而且该初始值可以在编译的时候就确定下来,那么这个final变量本质上就是一个”宏变量“,编译器会把程序中所用到该变量的地方直接替换成该变量的值。如果被赋的表达式只是基本的算术运算表达式或字符串连接运算,没有访问普通变量,调用方法,Java编译器同样会将这种final变量当成”宏变量“处理。

对于实例变量而言,可以在定义该变量时赋初始值之外,还可以在非静态初始化块、构造器中对它赋初始值,在这三个地方指定初始值的效果基本一样。但对于final实例变量而言,只有在定义该变量时指定初始值才会有”宏变量“的效果,在非静态初始化块、构造器中为final实例变量指定初始值则不会有这种效果。对于普通类变量而言,在定义时指定初始值,在静态初始化块中赋初始值的效果基本一样。但对于final类变量而言,只有在定义final类变量时指定初始值,系统才会对该final类变量执行”宏替换“


final方法不能重写
当final修饰某个方法时, 用于限制该方法不可被它的子类重写。
如果父类中某个方法使用了final修饰符进行修饰,这个方法将不可能被子类访问到,因此这个方法也不可能被它的子类重写。private和final同时修某个方法是没有太大意义,但是被Java语法允许。
如果父类和子类没有处于同一个包下,父类中包含的某个方法不使用访问控制符(相当于包访问权限)或者仅使用private访问控制符,那子类也是无法重写该方法的。

内部类中的局部变量
不仅匿名内部类,即使是普通内部类,在任何内部类中访问的局部变量都应该使用final修饰。
此处说的内部类指的是局部内部类,只有局部内部类(包括匿名内部类)才可以访问局部变量,普通静态内部类、非静态内部类不可能访问方法体内的局部变量。
Java要求所有被内部类访问的局部变量都使用final修饰,对于普通局部变量而言,它的作用域就是停留在该方法内,当方法执行结束,该局部变量也随之消失。但内部类则可能产生隐式的”闭包“闭包将使得局部变量脱离它所在的方法继续存在。
匿名内部类的实例生命周期没有结束的话,将一直可以访问局部变量的值,这就是内部类会扩大局部变量作用域的实例。
由于内部类可能扩大局部变量的作用域,如果再加上这个被内部类访问的局部变量没有使用final修饰,也就是说该变量的值可以随意改变,就会引起大乱。因此Java编译器要求所有被内部类访问的局部变量必须使用final修饰。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

java中的final变量

【java中为什么会有final变量】: final这个关键字的含义是“这是无法改变的”或者“终态的”; 那么为什么要阻止改变呢? java语言的发明者可能由于两个目的而阻止改变: 1).效率问题: ...

Java final修饰类/方法/变量的特点

public class Demo_Final { public static void main(String[] args) { // Son6 s=new Son6(); ...

java的final关键字——修饰变量

一、final修饰变量 final修饰变量不可变,这里是指引用不可变(Java中共提供两种数据类型,原始数据类型8种和引用类型),即它只指向初始时指向的那个对象,而不关心指向对象内容的变化。 fina...

java final修饰成员变量赋值的二种方法

java final修饰成员变量赋值的二种方法

java认证:Static和Final修饰类属性变量及初始化

1.static修饰一个属性字段,那么这个属性字段将成为类本身的资源,public修饰为共有的,可以在类的外部通过test.a来访问此属性;在类内部任何地方可以使用。如果被修饰为private私有,那...

关于java为什么在Method中局部内部类或者匿名内部类调用Method中定义的变量要用final修饰?

这个问题我碰到过好几次了,ye b

【Java关键字-Interface】为什么Interface中的变量只能是 public static final

三个关键字在接口中的存在原因: public:接口可以被其他接口继承,也可以被类实现,类与接口、接口与接口可能会形成多层级关系,采用public可以满足变量的访问范围; static:如果变量不是st...
  • claram
  • claram
  • 2015-08-26 14:15
  • 7180

Java匿名内部类访问外部类局部变量,为何需被标志为final?

原文地址 http://www.jianshu.com/p/609ca1c584ac 对于Java语言中的final使用,大家应该很熟悉,可以修饰类,表示不可继承;可以修饰方法,表...

修改java的静态final变量

请拷贝以下两个类,然后执行 类一: import java.lang.reflect.*; public class EverythingIsTrue { static void ...

得瑟一下jdk源代码解析,如何在运行时修改java final变量

先让各位看官看看sun的jdk Field类的代码, /* * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All righ...
  • barenx
  • barenx
  • 2013-02-15 06:17
  • 3995
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)