本文主要讲述内容:
-
final成员变量
-
final局部变量
-
final修饰基本类型变量和引用类型变量的区别
-
“宏替换”的final
-
final方法
-
final类
1.final成员变量
final指定的成员变量必须由程序员显式的进行指定初始值
归纳总结:final修饰的类变量,实例变量指定初始值的位置如下。
类变量:必须再静态初始化中指定初始值或声明该类变量的时候指定初始值,而且必须是其中的一种
实例变量:必须在非静态初始化块,声明该实例变量或者构造器中指定初始化,必须是其中的一个
代码如下:
public class FinalVariableTest {
final int a=6;
final String str;
final int c;
final static double d;
//final char ch;
//普通变量初始化块
{
str="hello";
//下面语句运行会发生错误
//a=9;
}
//静态变量初始化块
static {
d=5.6;
}
public FinalVariableTest(){
//在构造器中设置初始值
c=5;
}
public void changeFinal(){
//不能在普通方法中为final修饰的成员变量赋值
//d=1.2;
//不能在普通方法中为final设置的变量设置初始值
//ch='a';
}
public static void main(String[] args) {
FinalVariableTest ft=new FinalVariableTest();
System.out.println(ft.a);
System.out.println(ft.c);
System.out.println(ft.str);
System.out.println(ft.d);
new FinalVariableTest();
}
有如果在初始化之前访问由final修饰的变量,显然这是不可能的,但是Java提供方法对他可以进行访问
代码如下:
//final修饰符的访问机制
final int age;
{
//在没有进行显式初始化之前进行访问会引起错误
//System.out.println(age);
//可以通过方法对final修饰的成员变量进行访问,但是这里的成员变量还没有进行显式初始化,所以输出是0
printAge();
//进行显式初始化之后,输出为6
age=6;
System.out.println(age);
}
public void printAge(){
System.out.println(age);
}
2.局部变量
局部变量包括局部变量和形参
因为系统不会对局部变量进行初始化,必须由程序员进行显式初始化。因此使用final修饰的局部变量。既可以在定义是默认初始值也可以不指定初始值。
代码展示:
public class FinalLocaVariable {
public void test(final int a){
//不能对final修饰的形参进行赋值操作
//a=5;
}
public static void main(String[] args) {
final String str="hello";
//str="java";
final double d;
//初次赋值是正确的
d=5.6;
//再次赋值将发生错误
//d=6;
System.out.println(str);
System.out.println(d);
}
}
3,final修饰基本类型变量和引用类型变量的区别
final修饰基本类型变量时,如果该变量已经进行了初始化,则该变量的值不能再改变
final修饰引用类型变量的时候,引用指向的时某个对象的地址,所以该地址不能改变,但是对象可以发生变化(他一直在那,但是他变了,哈哈)
代码展示:
import java.lang.reflect.Array;
import java.util.Arrays;
public class Person {
private int age;
//构造一个无参的构造器
public Person(){};
//重载构造器
public Person(int age){
this.age=age;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public static void main(String[] args) {
//设置一个final修饰的数组
final int[] iArr={5,6,12,9};
//输出这个数组
System.out.println(Arrays.toString(iArr));
//对数组进行排序
Arrays.sort(iArr);
//排序后输出
System.out.println(Arrays.toString(iArr));
//改变数组中的只的置的值,这个可以做到,原因是final修饰不能改变的是他的地址,但是它引用的对象则可以进行改变
iArr[2]=-8;
System.out.println(Arrays.toString(iArr));
//下面这句话就会出现运行错误,因为地址发生了变动
//iArr=null;
//下面的原因与上面类似
final Person p=new Person(45);
p.setAge(23);
System.out.println(p.getAge());
//p=null;
//进行宏替换的final变量
final int a=5;
//这里再运行过程中直接将a转化成5,这就是“宏变量”,必须再定义是才有效果
System.out.println(a);
}
}
4,“宏替换”的final
如果一个final满足这三个条件,那么他就相当于一个直接量
- 使用final进行修饰
- 在定义final变量的时候进行了初始化。
- 该初始值在编译的时候就可以确定下来。
是不是看出来一个很重要的点,那就是在定义时就进行初始化。
代码展示:
//进行宏替换的final变量
final int a=5;
//这里再运行过程中直接将a转化成5,这就是“宏变量”,必须再定义是才有效果
System.out.println(a);
系统在接下来的就直接在能用到a的地方进行替换
5.final方法
final修饰的方法不能被重写,如果父类的方法不想被子类所重写,可以使用final进行修饰
则下面的代码运行会发生错误
public class FinalMethod(){
public void test(){}
}
class sub extends FinalMethod(){
public void test(){}
}
错误原因:因为重写了父类的final方法引发错误
重点来了,对于一个private修饰的方法,因为本身就不能被子类访问,所以子类无法进行重写,在加上final之后,如果子类“重写”这个方法的时候相当于重新定义一个方法,跟父类没有关系。
6.final类
单纯说明就是不可以有子类