浅析Java中的final关键字
一、final关键字的基本用法
final关键字可用来修饰类、方法和变量(包括成员变量和局部变量);
1 修饰类
final类表明该类不能被继承;
final类中的成员变量可根据需要设置为final,但final类中的所有成员方法都会被隐式地指定为final方法;
2 修饰方法
final方法表明继承于所在类的子类不能覆盖该方法;
注意:类的private方法会隐式地指定为final方法;
3 修饰变量
final变量若是基本数据类型,则其数值一旦在初始化后就不能修改;若是引用类型,则对其初始化后就不能再指向另一个对象;
二、深入了解final关键字
1 类的final变量和普通变量的区别?
final成员变量必须在定义时或构造器中进行初始化赋值,final局部变量必须在使用前初始化赋值,且final变量一旦被赋值就不能再被赋值;
举例1:
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = "hello";
String d = "hello";
String c = b + 2;
String e = d + 2;
System.out.println((a == c));
System.out.println((a == e));
}
}
输出:
true, false
分析:
当final变量是基本数据类型或String类型时,若在编译期间就能确定其值,则编译器会将其当作编译期常量使用,即使用该final变量的地方相当于直接访问这个常量,不需要运行时确定;
因此上述代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的 值,对于变量d的访问却需要在运行时通过链接来进行;
注意:只有在编译期间能确切知道final变量值的情况下,编译器才会进行这样的优化,如下面代码不会进行优化:
public class Test {
public static void main(String[] args) {
String a = "hello2";
final String b = getHello();
String c = b + 2;
System.out.println((a == c));
}
public static String getHello() {
return "hello";
}
}
2 被final修饰的引用变量指向的对象内容可变吗?
public class Test {
public static void main(String[] args) {
final MyClass myClass = new MyClass();
System.out.println(++myClass.i);
}
}
class MyClass {
public int i = 0;
}
输出:
1
分析:
引用变量被final修饰之后,虽然不能再指向其他对象,但是它指向的对象的内容是可变的;
3 final和static
public class Test {
public static void main(String[] args) {
MyClass myClass1 = new MyClass();
MyClass myClass2 = new MyClass();
System.out.println(myClass1.i);
System.out.println(myClass1.j);
System.out.println(myClass2.i);
System.out.println(myClass2.j);
}
}
class MyClass {
public final double i = Math.random();
public static double j = Math.random();
}
输出:
两个j值相同,两个i值不同;
分析:
static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变;
4 局部内部类为什么只能访问所在方法的final局部变量?
局部内部类是该类位于一个方法中;
局部内部类可访问局部变量,但局部内部类和局部变量的生命周期不同,即局部变量所在的方法执行结束就释放,但内部类对象若还有引用指向,方法执行结束仍存在,因此局部内部类就无法访问局部变量;Java采用复制的方法解决该问题;
若某一个变量的值在编译期见确定,则编译器默认在局部内部类的常量池中添加一个内容相同的字面量,因此局部内部类使用的是另一个局部变量,和方法中的局部变量完全独立;为防止修改另一个局部变量导致数据不一致,Java限定局部变量是final的,即不允许对其修改;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
A a = new A();
a.test();
}
}
class A{
public void test(){
int num = 20; // 添加final关键字即可
class B{
public void show(){
System.out.println(num); // Java8之前,编译不通过
}
}
B b = new B();
b.show();
}
}
注明:此文章是转载海子的博文,详情见:http://www.cnblogs.com/dolphin0520/p/3736238.html