finial关键字
1.final修饰的类无法被继承
public class FinalTest01{
public static void main(String[] args){
}
}
final class A{//A类被final修饰
}
//错误: 无法从最终A进行继承
class B extends A{
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2yTboRwo-1618583294368)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415104736101.png)]
2.final修饰的方法无法被覆盖
public class FinalTest02{
public static void main(String[] args){
}
}
class A{
public final void f(){
}
}
class B extends A{
//错误: B中的f()无法覆盖A中的f()
public void f(){
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5jpQ5vv-1618583294373)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415105051365.png)]
3.final修饰的变量只能赋一次值
public class FinalTest03{
//final修饰的变量只能赋值一次
public static void main(String[] args){
final int i = 1;
//错误: 无法为最终变量i分配值
i = 2;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qh03U5LR-1618583294374)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415105358966.png)]
4.final修饰的引用
public class FinalTest04{
public static void main(String[] args){
//final 修饰引用
final User u = new User("张三");
//u 指向另一个对象
u = new User("李四");
}
}
class User{
String name;
public User(){}
public User(String name){
this.name = name;
}
}
final修饰的变量只能赋一次值,引用也是变量,指向一个对象后,就不能再重新指向其他对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-736uXpTV-1618583294376)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415110556124.png)]
内存图示意:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SNRsgsbg-1618583294378)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415111850533.png)]
由上面可知,final修饰的引用指向的对象只有当方法执行完毕,局部变量u释放时,垃圾回收器才会回收该对象。
5.final修饰实例变量
思考:实例变量什么时候初始化?
在调用构造方法时,构造方法内部隐含了赋默认值的代码:
所以实例变量在调用构造方法时完成了初始化(new对象的时候)
class A{
String name;
int age;
public A(){
//this.name = null;
//this.age = 0;
}
}
因此,一般的实例变量不进行手动赋值时,系统会赋默认值,但是final修饰的实例变量必须进行手动赋值,并且只能赋一次值!
public class FinalTest05{
public static void main(String[] args){
}
}
class User{
//final修饰的实例变量没初始化
//错误: 变量 age 未在默认构造器中初始化
final int age;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qFEh5Z7u-1618583294380)(C:\Users\15195891836\AppData\Roaming\Typora\typora-user-images\image-20210415112928201.png)]
实际上,此时针对finala修饰的实例变量,构造器不再进行默认初始化,必须手动初始化:
即要么定义时初始化,要么在构造方法中初始化!
1.声明变量时初始化
public class FinalTest05{
public static void main(String[] args){
}
}
class User{
final int age = 10;
public User(){
}
}
2.构造方法中初始化
public class FinalTest05{
public static void main(String[] args){
}
}
class User{
final int age ;
public User(){
this.age = 10;
}
public User(int age){
this.age = age;
}
}
6.常量
final修饰的实例变量一般和static联合使用,称为常量
思考:下面的代码定义的实例变量有什么缺点?
public class FinalTest06{
public static void main(String[] args){
}
}
class Chinese{
String name;
String sex;
//中国人国籍都是中国
String country;
}
实际上Chinese类型的对象国籍属性都是中国,只需要定义一次即可,不需要重复初始化(final)。若定义为一般的实例变量,会在堆内存中占用内存,造成浪费(static)。
public class FinalTest06{
public static void main(String[] args){
}
}
class Chinese{
String name;
String sex;
//中国人国籍都是中国
public static final String country = "中国";
}
final修饰的实例变量必须初始化,且只能赋值一次。就意味着后续不能修改也无法修改。所以一般常量定义为public,不需要私有化。
注意:
常量的变量名一般全部大写,单词之间用下划线分开
public static final PI = 3.1415926;