我们从数据 方法 类 三个方面去讨论fianl关键字。 <br /> 7.8.1final数据<br /> 有时候我们需要通过final来告诉程序一个数据是不变的。在对象的引用被fianl修饰时,不变的是其引用也就是引用在栈中的存储空间,此时,这个引用就不能去问他指向另一个对象了。然而对象自身的属性是可以被修改的。
1.一个永远不变的编译时的常量
2.在运行时初始化的值,我们不需要他去改变。
第一种情况:编译的常量必须是java所指的基本数据类型。而且要用fianl修饰,同时对这个常量进行定义的时候必须进行赋值。<br />第二种情况:运行时初始化的值,我们不需要去改变。对此我们需要用static和fianl一起去修饰。当一个域被static和fianl公共修饰时,他只是占据了一段不能被修改的存储空间。对于这种域我们常用大写来表示,并且用下划线去区分每个单词。<br /> 通过下面的这个列子我们来区分static fianl修饰的域和fianl修饰的域有何区别:
package com.zx.test07.test07_01;
import java.util.Random;
class Test {
Test() {
System.out.println("Test()");
}
}
public class FianlAndStaticDemo {
String name;
public FianlAndStaticDemo(String s){
name=s;
}
//1.static fianl 和 fianl 修饰的引用类型有何不同?
static final Test TEST = new Test();
final Test test1 = new Test();
//2. static fianl 和 fianl 修饰的String类型有何不同?
static final String STR_ONR="static final ";
final String str_tow="final String";
//3.static fianl 和fianl 修饰的基本类型有何不同?
private static Random random=new Random(47);
static final int SFI=random.nextInt();
final int fi=random.nextInt();
@Override
public String toString() {
return name+" test的地址值:"+TEST +" "+"test1的地址值:"+test1+" "+"STR_ONR的值"+STR_ONR+" "+"str_tow的值"+str_tow
+" "+"SFI的值"+SFI+" "+"fi的值"+fi;
}
public static void main(String[] args) {
FianlAndStaticDemo fianlAndStaticDemo01 = new FianlAndStaticDemo("001");
FianlAndStaticDemo fianlAndStaticDemo02 = new FianlAndStaticDemo("002");
FianlAndStaticDemo fianlAndStaticDemo03 = new FianlAndStaticDemo("003");
System.out.println(fianlAndStaticDemo01);
System.out.println(fianlAndStaticDemo02);
System.out.println(fianlAndStaticDemo03);
}
}
//output:
Test()
Test()
Test()
Test()
001 test的地址值:com.zx.test07.test07_01.Test@4554617c test1的地址值:com.zx.test07.test07_01.Test@74a14482 STR_ONR的值static final str_tow的值final String SFI的值-1172028779 fi的值1717241110
002 test的地址值:com.zx.test07.test07_01.Test@4554617c test1的地址值:com.zx.test07.test07_01.Test@1540e19d STR_ONR的值static final str_tow的值final String SFI的值-1172028779 fi的值-2014573909
003 test的地址值:com.zx.test07.test07_01.Test@4554617c test1的地址值:com.zx.test07.test07_01.Test@677327b6 STR_ONR的值static final str_tow的值final String SFI的值-1172028779 fi的值229403722
结论:<br /> 1.static和fianl修饰的引用变量只执行一次且不会开辟新的储存空间,而fianl修饰的变量会在每次创建新的是列时候被执行一次,且会为新的实例开辟新的存储空间<br /> 2.static和fianl修饰的String 类型是不变的也是只执行一次,而fianl修饰的String 类型也会在每次创建实例的时候执行(因为String类是被fianl修饰的)所以每次的值相同的。<br /> 3.static和fianl修饰的基本类型变量也只会执行一次,而fianl修饰的变量也会在每次创建实例的时候去执行。<br /> 扩展:我们能对staticfinal修饰的域进行修改,并且同一个对象的其他实例也可以可以感知,而且每一次新的修改都会覆盖上一个实例的修改。
package com.zx.test07.test07_01;
class School{
String s_name;
School(){
System.out.println("school");
}
public void setS_name(String s_name) {
this.s_name = s_name;
}
public String getS_name() {
return s_name;
}
}
public class StaticDemo {
static final School S=new School();
@Override
public String toString() {
return " "+S;
}
public static void main(String[] args) {
StaticDemo staticDemo01= new StaticDemo();
StaticDemo staticDemo02 = new StaticDemo();
StaticDemo staticDemo03= new StaticDemo();
staticDemo01.S.setS_name("小学");
System.out.println(staticDemo01.S.getS_name());
staticDemo02.S.setS_name("中学");
System.out.println(staticDemo02.S.getS_name());
staticDemo03.S.setS_name("高中");
System.out.println(staticDemo03.S.getS_name());
}
}
空白fianl:指声明final但有未给定初始值的域。所以说只要是在构造器之前执行的域都可以为空白fianl初始化。
class Fianl{
fianl int i;
{//普通代码先构造器执行
i=setInt();
}
int SetInt(){
return 3;
}
}
2.fianl方法:
1.fianl修饰的方法,是无法被继承的,其中如果是private修饰的方法,无论是否有fianl修饰都是无法被继承的(从访问权限解释)
2.fianl修饰的方法参数是无法被修改的只能引用参数,final方法不是基类接口的一部分,对于扩展类来说,与基类final修饰的方法同名,仅仅是生成了一个新的方法,并没有覆盖基类的方法。
package com.zx.test07.test07_01;
class Student{
Student(){
System.out.println("Student()");
}
public void test01(final String name){
System.out.println("....");
}
private void test02{
System.out.println(".....");
}
}
public class FianlAndPrivate extends Student {
@Override
public void test01(String name) {
super.test01(name);
}
/*
* public void test01(String nam) {
super.test01(name);
} 这是错误的
*
* */
public static void main(String[] args) {
FianlAndPrivate fianlAndPrivate = new FianlAndPrivate();
// fianlAndPrivate.test02();不能调用父类的private 和fianl修饰的方法
}
}
fianl类:被fianl修饰的类是不能继承的,有于fianl类不能被继承,所以说fianl类中所有方法都是隐形定义为fianl的。但里面的域可以根据自己的选择去定义是否为fianl。
package com.zx.test07.test07_01;
final class Student{
final String name="高中";
int i;
Student(){
System.out.println("Student()");
}
public void test01(final String name){
System.out.println("....");
}
private void test02{
System.out.println(".....");
}
}
public class FianlAndPrivate extends Student {//是不能继承的,编译器会报错
}