final关键字

Java中的final关键字可以用来修饰类、方法和变量(包括实例变量和局部变量)

Tip:

实例变量是类中方法外定义的变量,实例变量可以使用访问修饰符public和private修饰,使用public修饰说明该变量对子类可见,使用private修饰则子类不可见,该变量只能在本类可见,实例变量具有默认值;

局部变量是在方法中定义的变量,不能用访问修饰符修饰,但是可以使用final关键字修饰(局部变量本省就是一种有限制的变量,只可以局部调用,因此没有必要使用访问修饰符修饰)

final关键字的基本用法
final修饰类
使用final修饰类则该类不能被继承,同时类中的所有成员方法都会被隐式定义为final方法(只有在需要确保类中的所有方法都不被重写时才使用final修饰类)。

final修饰类的成员变量是可以更改的

public final class FinalClass{

int i = 1;

void test(){
	System.out.println("FinalClass:test");
}

public static void main( String[] args ){
	FinalClass ficl = new FinalClass();

	System.out.println("ficl.i = " + ficl.i);
	ficl.i = 2;
	System.out.println("ficl.i = " + ficl.i);
}

}
final修饰方法
使用final修饰方法可以将方法“锁定”,以防止任何继承类对方法的修改,也即使用final修饰方法,则子类无法重写(但并不影响继承和重载,即子类调用父类方法不受影响)。

final修饰变量
使用final关键字修饰变量是使用最多的情况

使用final修饰变量的值不能做再次更改,即不能重新赋值
如果final修饰的变量是基本数据类型,则变量的值不可更改;
如果final修饰的变量是引用数据类型,则该变量不能再次指向其他引用(如重新指向新的对象或数组)但是该变量本身的内容可以再做修改(如数组本身的内容,或者对象的属性的修改)

无论final修饰实例变量还是局部变量,都必须在使用前显式赋初值
Java中的实例变量系统会对其默认赋初值,但是局部变量必须先声明后赋值再使用:

在下面的例子中,没有对src赋初值,如果程序正确,那么会在2步骤中给src赋值,但是如果2步骤中读文件出现问题,那么在4步骤中使用src就会出错,因此从程序的健壮性考虑,应对src赋初值,即0步骤

public void fun(){

//BufferedImage src = null;//0. 声明的同时赋值
BufferedImage src;//1. 这里不用赋初值,也不会出错
try{
	src = ImageIO.read(new File("1.jpg"));//2.
} catch (Exception e){
//3. 如果出异常了就会进入这里,那么src可能无法被赋值
}

System.out.println(src.getHeight()); //4. src不一定有值,所以无法使用

}

虽然对于实例变量,系统会默认赋初值,但是Java仍然规定final修饰的实例变量必须显式赋初值。实例变量显式赋值的时机可以是在声明时直接赋值,也可以先声明,后在构造方法中赋值(对于含有多个构造方法,必须在每个构造方法中都显示赋值)

如果静态变量同时被final修饰则可以将变量视为全局变量,即在整个类加载期间,其值不变。(static保证变量属于整个类,在类加载时只对其分配一次内存;final保证变量的值不被改变)
final 关键字相关问题
final变量和普通变量的区别
final变量一旦被初始化赋值之后,就不能再被赋值了。

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));//输出true
System.out.println((a == e));//输出false
}
}
当final变量是基本数据类型以及String类型时,如果在编译期间能知道它的确切值,则编译器会把它当做编译期常量使用。也就是说在用到该final变量的地方,相当于直接访问的这个常量,不需要在运行时确定。(类似于c语言中的宏替换)

上面的一段代码中,由于变量b被final修饰,因此会被当做编译器常量,所以在使用到b的地方会直接将变量b 替换为它的 值。而对于变量d的访问却需要在运行时通过链接来进行。

final和static
使用final修饰是用以保证变量不被改变,而使用static修饰成员变量,则成员变量在类中只保存一份副本。

在下列代码中,i的两次输出都不一样,而j的两次输出为同一值。

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();
}

原文地址:https://www.cnblogs.com/1121cyy/p/14215658.html