final关键字
1、final是Java语言中的一个关键字
2、final表示最终的,不可变的
3、final修饰的类
final修饰的类无法被继承
4、final修饰的方法
final修饰的方法无法被覆盖,被重写
5、final修饰的变量
final修饰的变量,只能赋一次值
final修饰的局部变量,一旦赋值,不能重新赋值
局部变量没有初始值,只有成员变量才有初始值。
final修饰的引用,一旦指向某个对象,则不能再重新指向其他对象,但该引用指向的对象内部的数据是可以修改的
final修饰的实例变量必须手动初始化,不能采用系统默认值
final修饰的实例变量一般和static联合使用,称为常量
final修饰的类
java
class A {}
class B extends A {}
B类继承A类,相当于对A类的功能进行扩展。
如果不希望别人对A类进行扩展,可以给A类加个final关键字,这样A类就无法继承了。
// 报错,无法从final String进行继承
java
class MyString extends String {}
final表示最终的,final修饰的类,不能被继承
java
final class A {}
final修饰的方法
java
class C {
public void doSome(){
System.out.println("C's doSome...");
}
}
class D extends C {
public void doSome(){
System.out.println("D's doSome...");
}
}
若在C类的方法doSome()上加final,那么编译报错为:D中的doSome()无法覆盖C中的doSome(),被覆盖的方法为final
java
class C {
public final void doSome(){
System.out.println("C's doSome...");
}
}
class D extends C {
// Error:编译报错
public void doSome(){
System.out.println("D's doSome...");
}
}
final修饰的方法无法被覆盖,被重写
final修饰的变量
final修饰的局部变量
java
public static void main(String[] args){
// 局部变量
int i = 100;
// 重新赋值
i = 200;
// 局部变量
final int k = 100;
// 重新赋值
// Error:无法为final变量k重新赋值
k = 300;
}
final修饰的局部变量,一旦赋值不能重新赋值
final修饰的引用
final修饰的变量,如果这个变量是一个 "引用" 会怎样?
《重点》final修饰的变量只能赋一次值
"引用"是不是一个变量呢???是
java
public class FinalTest02{
public static void main(String[] args){
Person p1 = new Person(20);
System.out.println(p1.age);
// -----------------------
// 代码不管怎么变,p也是一个变量(只不过这里,它有一个特殊的名字:引用)
final Person p = new Person(30);
// Error:无法为final变量p重新赋值
//p = new Person(30);
// Error:无法为final变量p重新赋值
//p = null;
}}
p.age = 40;
System.out.println(p.age);
/*
final int i = 10;
// 不允许的
i = 20;
*/
class Person{
int age;
public Person(){
}
public Person(int age){
this.age = age;
}
}
final修饰的引用,
该引用只能指向一个对象,并且它只能永远指向该对象,无法再指向其他对象。
并且在该方法执行过程中,该引用指向对象之后,该对象不会被垃圾回收器回收。
直到当前方法结束,才会释放空间。
虽然final的引用指向对象A后,不能再重新指向对象B。
但是对象A内部的数据可以被修改。

final修饰的实例变量
《重点:万变不离其宗》:final修饰的变量只能赋值一次。(这句话到哪都好使)
你是否还记得:实例变量如果没有手动赋值的话,系统会赋默认值。
实例变量在什么时候赋值(初始化)?
构造方法执行的过程中赋值。(new的时候赋值)
终极结论:
final修饰的实例变量,系统不管赋默认值,要求程序员必须手动赋值。
这个手动赋值,在变量后面赋值可以,在构造方法中赋值也可以。
java
public class FinalTest03{
public static void main(String[] args){
}
}
class User{
// 实例变量
// Error:final变量age未在默认构造器中初始化
//final int age;
// 实例变量
// 可以,因为程序员手动赋值了
final double height = 1.8;
// 实例变量
final double weight;
// 构造方法
public User(){
// 只要赶在系统赋默认值之前赋值就行
this.weight = 80;
// 系统赋默认值是在这个时候(构造方法执行的时候)
//weight = 0;
}
}
final修饰的常量
final修饰的实例变量一般添加static修饰。
终极结论:
static final联合修饰的变量称为"常量"。
常量名 建议全部大写,每个单词之间采用下划线衔接。
常量:实际上常量和静态变量一样,区别在于:
常量的值不能变。
常量和静态变量,都是存储在方法区,并且都是在类加载时初始化。
常量一般都是公开的:public的
java
public class FinalTest04{
public static void main(String[] args){
System.out.println(Chinese.COUNTRY);
// 常量是无法重新赋值的
//Chinese.COUNTRY = "美国";
}
}
class Chinese{
// 身份证号,每个人都不一样,对象级别的
String idCard;
// 姓名,对象不同姓名不一样
String name;
// 国家的值是一个固定值:"中国"
// 实例变量在堆中,一个对象一份。100个对象100份。
// 实例变量既然使用final修饰了,说明该实例变量值不会随着对象的变化而变化。
// 该实例变量前面应该添加:static关键字,变为静态的,存储在方法区
//static final String country = "中国";
public static final String COUNTRY = "中国";
// i永远都是10,创建100个对象,i也是10
// i是10是永远不会发生改变的,既然这样,没必要声明为实例变量,最好是静态的,节省内存
static final int i = 10;
}
class MyMath{
// 常量一般都是public公开的/
// 数学中的 π 是永远不会变的
public static final double PI = 3.1415926;
}
final关键字总结
- final修饰的类无法被继承
- final修饰的方法无法被覆盖
- final修饰的变量只能赋一次值
- final修饰的引用一旦指向某个对象,则不能再重新指向其他对象,但该引用指向的对象内部的数据是可以修改的
- final修饰的实例变量必须手动初始化,不能采用系统默认值
- final修饰的实例变量一般和static联合使用,称为常量
- public static final double PI = 3.1415926;