Java基础(三)--final关键字
final通常是指"不可改变的",例如我们使用的常量
通常可以有三种使用情况:
一、final修饰数据
如果final修饰数据,也就是通常所说的常量,从字面上看,常量就是不能修改的,和变量是一个对立面
1、定义的时候必须有初始值,否则会编译错误
原因:
public int i = 123;
在类加载的准备阶段i的值为0,而不是123。赋值123的过程是在初始化阶段
但是如果i被final修饰,编译器会生成Constantvalue属性,在准备阶段会根据Constantvalue的设置将i赋值为123
所以,常量必须有初始值,编译器不会给它零值
空白final:
声明为final但是没有给定初值,在构造器内进行初始化,能够保证一定的灵活性,而且符合final在使用前被初始化
@Data @NoArgsConstructor @AllArgsConstructor public class Test1 { public int i = 0; } public class Test { private final int i; private final Test1 test1; public Test() { i = 0; test1 = new Test1(); } public Test(int i) { this.i = i; test1 = new Test1(i); } }
PS:常量并不是在编译期就能知道它的值,可以在运行时生成的
2、修饰对象引用
final修改引用的时候和修饰基本数据类型有差别
2.1).修饰基本数据类型:数值不能修改
2.2).修改引用类型:
final修饰的引用初始化的时候指向一个对象之后,就不会指向别的对象。被指向的对象是可以修改的
public class Test1 { public int i = 0; }
3、final参数
和一般修饰数据和引用没有什么区别,主要匿名内部类中使用,会在后面讲
下面的"常量和变量的区别",内容来自:https://www.cnblogs.com/dolphin0520/p/3736238.html,也推荐大家去看,内容更加详细
常量和普通变量的区别?
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,这就是区别了
PS:只有在编译期间能确切知道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"; } }
结果:false
二、final修饰方法
使用final修饰方法的原因有两个:
1、防止方法被重写
2、效率:早期Java对final方法进行优化
private方法默认也是final,是否加上final都是无所谓的
public class Test { private void f1() { } } public class Test1 extends Test{ private void f1() { } }
这种场景并不是重写
三、final修饰类
如果final修饰类的时候,表示该类无法被继承,某种情况下,这是出于安全考虑,不希望有子类。
所有方法都会被隐式指定为final