1. 我们从数据 方法 三个方面去讨论fianl关键字。 <br /> 7.8.1final数据<br /> 有时候我们需要通过final来告诉程序一个数据是不变的。在对象的引用被fianl修饰时,不变的是其引用也就是引用在栈中的存储空间,此时,这个引用就不能去问他指向另一个对象了。然而对象自身的属性是可以被修改的。
    1. 1.一个永远不变的编译时的常量
    2. 2.在运行时初始化的值,我们不需要他去改变。
    1. 第一种情况:编译的常量必须是java所指的基本数据类型。而且要用fianl修饰,同时对这个常量进行定义的时候必须进行赋值。<br />第二种情况:运行时初始化的值,我们不需要去改变。对此我们需要用staticfianl一起去修饰。当一个域被staticfianl公共修饰时,他只是占据了一段不能被修改的存储空间。对于这种域我们常用大写来表示,并且用下划线去区分每个单词。<br /> 通过下面的这个列子我们来区分static fianl修饰的域和fianl修饰的域有何区别:
    1. package com.zx.test07.test07_01;
    2. import java.util.Random;
    3. class Test {
    4. Test() {
    5. System.out.println("Test()");
    6. }
    7. }
    8. public class FianlAndStaticDemo {
    9. String name;
    10. public FianlAndStaticDemo(String s){
    11. name=s;
    12. }
    13. //1.static fianl 和 fianl 修饰的引用类型有何不同?
    14. static final Test TEST = new Test();
    15. final Test test1 = new Test();
    16. //2. static fianl 和 fianl 修饰的String类型有何不同?
    17. static final String STR_ONR="static final ";
    18. final String str_tow="final String";
    19. //3.static fianl 和fianl 修饰的基本类型有何不同?
    20. private static Random random=new Random(47);
    21. static final int SFI=random.nextInt();
    22. final int fi=random.nextInt();
    23. @Override
    24. public String toString() {
    25. return name+" test的地址值:"+TEST +" "+"test1的地址值:"+test1+" "+"STR_ONR的值"+STR_ONR+" "+"str_tow的值"+str_tow
    26. +" "+"SFI的值"+SFI+" "+"fi的值"+fi;
    27. }
    28. public static void main(String[] args) {
    29. FianlAndStaticDemo fianlAndStaticDemo01 = new FianlAndStaticDemo("001");
    30. FianlAndStaticDemo fianlAndStaticDemo02 = new FianlAndStaticDemo("002");
    31. FianlAndStaticDemo fianlAndStaticDemo03 = new FianlAndStaticDemo("003");
    32. System.out.println(fianlAndStaticDemo01);
    33. System.out.println(fianlAndStaticDemo02);
    34. System.out.println(fianlAndStaticDemo03);
    35. }
    36. }
    37. //output:
    38. Test()
    39. Test()
    40. Test()
    41. Test()
    42. 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
    43. 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
    44. 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
    1. 结论:<br /> 1.staticfianl修饰的引用变量只执行一次且不会开辟新的储存空间,而fianl修饰的变量会在每次创建新的是列时候被执行一次,且会为新的实例开辟新的存储空间<br /> 2.staticfianl修饰的String 类型是不变的也是只执行一次,而fianl修饰的String 类型也会在每次创建实例的时候执行(因为String类是被fianl修饰的)所以每次的值相同的。<br /> 3.staticfianl修饰的基本类型变量也只会执行一次,而fianl修饰的变量也会在每次创建实例的时候去执行。<br /> 扩展:我们能对staticfinal修饰的域进行修改,并且同一个对象的其他实例也可以可以感知,而且每一次新的修改都会覆盖上一个实例的修改。
    1. package com.zx.test07.test07_01;
    2. class School{
    3. String s_name;
    4. School(){
    5. System.out.println("school");
    6. }
    7. public void setS_name(String s_name) {
    8. this.s_name = s_name;
    9. }
    10. public String getS_name() {
    11. return s_name;
    12. }
    13. }
    14. public class StaticDemo {
    15. static final School S=new School();
    16. @Override
    17. public String toString() {
    18. return " "+S;
    19. }
    20. public static void main(String[] args) {
    21. StaticDemo staticDemo01= new StaticDemo();
    22. StaticDemo staticDemo02 = new StaticDemo();
    23. StaticDemo staticDemo03= new StaticDemo();
    24. staticDemo01.S.setS_name("小学");
    25. System.out.println(staticDemo01.S.getS_name());
    26. staticDemo02.S.setS_name("中学");
    27. System.out.println(staticDemo02.S.getS_name());
    28. staticDemo03.S.setS_name("高中");
    29. System.out.println(staticDemo03.S.getS_name());
    30. }
    31. }

    空白fianl:指声明final但有未给定初始值的域。所以说只要是在构造器之前执行的域都可以为空白fianl初始化。

    1. class Fianl{
    2. fianl int i;
    3. {//普通代码先构造器执行
    4. i=setInt();
    5. }
    6. int SetInt(){
    7. return 3;
    8. }
    9. }

    2.fianl方法:
    1.fianl修饰的方法,是无法被继承的,其中如果是private修饰的方法,无论是否有fianl修饰都是无法被继承的(从访问权限解释)
    2.fianl修饰的方法参数是无法被修改的只能引用参数,final方法不是基类接口的一部分,对于扩展类来说,与基类final修饰的方法同名,仅仅是生成了一个新的方法,并没有覆盖基类的方法。

    1. package com.zx.test07.test07_01;
    2. class Student{
    3. Student(){
    4. System.out.println("Student()");
    5. }
    6. public void test01(final String name){
    7. System.out.println("....");
    8. }
    9. private void test02{
    10. System.out.println(".....");
    11. }
    12. }
    13. public class FianlAndPrivate extends Student {
    14. @Override
    15. public void test01(String name) {
    16. super.test01(name);
    17. }
    18. /*
    19. * public void test01(String nam) {
    20. super.test01(name);
    21. } 这是错误的
    22. *
    23. * */
    24. public static void main(String[] args) {
    25. FianlAndPrivate fianlAndPrivate = new FianlAndPrivate();
    26. // fianlAndPrivate.test02();不能调用父类的private 和fianl修饰的方法
    27. }
    28. }

    fianl类:被fianl修饰的类是不能继承的,有于fianl类不能被继承,所以说fianl类中所有方法都是隐形定义为fianl的。但里面的域可以根据自己的选择去定义是否为fianl。

    1. package com.zx.test07.test07_01;
    2. final class Student{
    3. final String name="高中";
    4. int i;
    5. Student(){
    6. System.out.println("Student()");
    7. }
    8. public void test01(final String name){
    9. System.out.println("....");
    10. }
    11. private void test02{
    12. System.out.println(".....");
    13. }
    14. }
    15. public class FianlAndPrivate extends Student {//是不能继承的,编译器会报错
    16. }