Java中的final变量、final⽅法和final类
1、final变量
final关键字可⽤于变量声明,⼀旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。例如,在类中定义PI值,可以使⽤如下语句:
final double PI=3.14;
在Java中定义全局常量,通常使⽤public static final修饰,这样的常量只能在定义是被赋值。
public static final double PI_VAULE = 3.14;
规范:被定义为final的常量定义时需要使⽤⼤写字母命名,并且中间使⽤下划线进⾏连接。
常量⽰例:
import java.util.Random;
class Test
{
int i = 0;
}
/**
* 常量⽰例
*
* @author pan_junbiao
*
*/
public class FinalData
{
static Random rand = new Random();
private final int VALUE_1 = 9; // 声明⼀个final常量
private static final int VALUE_2 = 10; // 声明⼀个final、static常量 private final Test test = new Test(); // 声明⼀个final引⽤
private Test test2 = new Test(); // 声明⼀个不是final的引⽤
private final int[] a = { 1, 2, 3, 4, 5, 6 }; // 声明⼀个定义为final的数组 private final int i4 = Int(20);
private static final int i5 = Int(20);
public String toString()
{
return "i4值:" + i4 + " i5值:" + i5 + " ";
}
public static void main(String[] args)
{
FinalData data = new FinalData();
// 报错:不能改变定义为final的常量值
// data.VALUE_1 = 8;
// 报错:不能改变定义为final的常量值
// data.VALUE_2 = 9;
// 报错:不能将定义为final的引⽤指向其他引⽤
// st = new Test();
// 正确:可以对指定为final的引⽤中的成员变量赋值
// 正确:可以将没有定义为final的引⽤指向其他引⽤
// 报错:不能对定义为final的数组赋值
// int b[] = { 7, 8, 9 };
// data.a = b;
// 但是final的数组中的每⼀项内容是可以改变的
for (int i = 0; i < data.a.length; i++)
{
data.a[i] = 9;
}
System.out.println(data);
System.out.println("data2");
System.out.println(new FinalData());
}
}
执⾏结果:
从上述执⾏结果中可以发现i5的值是相同的。
全局常量:
我们知道⼀个被定义为final的对象引⽤只能指向唯⼀⼀个对象,不可以将它再指向其它对象,但是⼀个对象的值却是可以改变的,那么为了使⼀个常量真正做到不可更改,可以将常量声明为static final。
⽰例:在项⽬中创建FinalStaticData类,在该类中创建Random类的对象,在主⽅法中分别输出类中定
义的final变量a1与a2。
import static java.lang.System.out;
import java.util.Random;
/**
* FinalStaticData类
*
* @author pan_junbiao
*
*/
public class FinalStaticData
{
private static Random rand = new Random(); // 实例化⼀个Random类对象
// 随机产⽣0~10之间的随机数赋予定义为final的a1
private final int a1 = Int(10);
// 随机产⽣0~10之间的随机数赋予定义为static final的a2
private static final int a2 = Int(10);
public static void main(String[] args)
{
FinalStaticData fdata = new FinalStaticData(); // 实例化⼀个对象
// 调⽤定义为final的a1
out.println("重新实例化对象调⽤a1的值:" + fdata.a1);
// 调⽤定义为static final的a2
out.println("重新实例化对象调⽤a2的值:" + fdata.a2);
// 实例化另外⼀个对象
FinalStaticData fdata2 = new FinalStaticData();
out.println("重新实例化对象调⽤a1的值:" + fdata2.a1);
out.println("重新实例化对象调⽤a2的值:" + fdata2.a2);
}
}
运⾏结果:
从本⽰例运⾏结果中可以看出,定义为final的常量不是恒定不变的,将随机数赋予定义为final的常量,可以做到每次运⾏程序时改变a1的值。但是a2与a1不同,由于它被声明为static final形式,所以在内存中为a2开辟了⼀个恒定不变的区域,当再次实例化⼀个FinalStaticData对象时,仍然指向a2这块内存区域,所以a2的值保存不变。a2是在装载时被初始化,⽽不是每次创建新对象时被初始化;⽽a1会重新实例化对象时被更改。
最后总结⼀下在程序中final数据可以出现的位置,如下程序。
/**
* 总结⼀下在程序中final数据可以出现的位置
*
* @author pan_junbiao
*
*/
public class FinalDataTest
{
// final成员变量不可更改
final int VALUE_ONE = 6;
// 在声明final成员变量时没有赋值,称为空⽩final
final int BLANK_FINALVAULE;
// 在构造⽅法中为空⽩final赋值
public FinalDataTest()
{
BLANK_FINALVAULE = 8;
}
// 设置final参数,不可以改变参数x的值
int doIt(final int x)
{
return x + 1;
}
// 局部变量定义为final,不可以改变i的值
void doSomething()
{
final int i = 7;
}
}
2、final⽅法
⾸先,我们应该了解定义为final的⽅法不能被重写。
将⽅法定义为final类型可以防⽌任何⼦类修改该类的定义与实现⽅式,同时定义为final的⽅法执⾏效率要⾼于⾮final⽅法。在修饰权限中曾经提到过private修饰符,如果⼀个⽗类的某个⽅法被设置为private修饰符,⼦类将⽆法访问该⽅法,⾃然⽆法覆盖该⽅法,所以⼀个定义为private的⽅法隐式被指定为final类型,这样⽆须将⼀个定义为private的⽅法再定义为final类型。
语法:
private final void test()
{
}
3、final类
定义为final的类不能被继承。
如果希望⼀个类不允许任何类继承,并且不允许其他⼈对这个类有任何改动,可以将这个类设置为final形式。
final类的语法如下:
final 类名{}
如果将某个类设置为final形式,则类中的所有⽅法都被隐式设置为final形式,但是final类中的成员变量可以被定义为final或⾮final形式。
⽰例:在项⽬中创建FinalClass类,在类中定义doit()⽅法和变量a,实现在主⽅法中操作变量a⾃增。
/**
nextint()方法
* 定义final类
*
* @author pan_junbiao
*
*/
final class FinalClass
{
int a = 3;
void doit()
{
}
public static void main(String args[])
{
FinalClass f = new FinalClass();
f.a++;
System.out.println(f.a); // 结果:4
}
}
4、总结
下⾯总结了⼀些使⽤final关键字的好处:
(1)final关键字提⾼了性能。JVM和Java应⽤都会缓存final变量。
(2)final变量可以安全的在多线程环境下进⾏共享,⽽不需要额外的同步开销。
(3)使⽤final关键字,JVM会对⽅法、变量及类进⾏优化。
不可变类:
创建不可变类要使⽤final关键字。不可变类是指它的对象⼀旦被创建了就不能被更改了。String是不可变类的代表。不可变类有很多好处,譬如它们的对象是只读的,可以在多线程环境下安全的共享,不⽤额外的同步开销等等。
关于final的重要知识点:
(1)final关键字可以⽤于成员变量、本地变量、⽅法以及类。
(2)final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
(3) 你不能够对final变量再次赋值。
(4)本地变量必须在声明时赋值。
(5)在匿名类中所有变量都必须是final变量。
(6)final⽅法不能被重写。
(7)final类不能被继承。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。