• java final 关键字


    根据上下文环境,Java的关键字final的含义存在着细微的区别,但通常它指的是"这是无法改变的."不想做改变可能出于两种原因:设计或效率.由于这两个原因相差很远,所以final有可能误用

    以下谈到了final的三种情况:数据.方法和类

    一.final数据

    恒定不变的数据比如

    1.一个永不改变的编译时常量  //java中这类常量必须是基本数据类型

    2.一个在运行时时被初始化的值,而你不希望它被改变.

    3.当对对象使用final时,不变的只是指向对象的引用无法被改变,而对象自身可以被修改

    package object;
    import java.util.*;
    import static net.mindview.util.Print.*;
    class Value{
        int i ;//Package access
        public Value(int i){ this.i = i;}
    }
    public class FinalData{
        private static Random rand = new Random(47);
        private String id;
        public FinalData(String id){ this.id = id;}
        //Can be fianl int valueOne = 9
        private final int valueOne = 9;
        private static final int VALUE_TWO = 99;// 根据惯例既是static又是final的域将用大写表示
        public static final int VAL_THREE = 39; //public 说明可以被用于包外,定义为static,才强调只有一份,定义为final,则说明它是一个常量
        private final int i4 = rand.nextInt(20);
        static final int INT_5 = rand.nextInt(20);
        private Value v1 = new Value(11);
        private final Value v2 = new Value(33);
        private static final Value VAL_3 = new Value(33);
        //Arrays:
        private final int []a = {1,2,3,4,5,6};
        public String toString()
        {
            return id + ": " + "i4 = "  + i4 + ", INT_5= " + INT_5;
        }
    public static void main(String[] args)
    {
        FinalData fd1 = new FinalData("fd1");
        //! fd1.valueOne++;; // Error: can't change value
        fd1.v2.i++; //object isn't constant
        fd1.v1 = new Value(9); //ok -- no final
        for(int i = 0; i < fd1.a.length; i++)
            fd1.a[i]++;//Object isn't constant
        //! fd1.v2 = new Value(0); //Error: can't
        //! fd1.VAL_3 = new Value(1    ;//Change reference
        //! fd1.a = new int[3];
        print(fd1);
        print("Creading new FinalData");
        FinalData fd2 = new FinalData("fd2");
        print(fd1);
        print(fd2);
    }
    }
    /* output:
     * fd1: i4 = 15, INT_5= 18
     *Creading new FinalData
     *fd1: i4 = 15, INT_5= 18
     *fd2: i4 = 13, INT_5= 18
     *///:~

    二:空白final

    java 允许生产"空白final",所谓空白final是指被声明为final但又未给初值的域(field),无论什么情况,编译器都会确保空白final字使用前必须被初始化,但是,空白final在关键字final的使用上提供了很大的灵活性,为此,一个类中的final域就可以做到根据对象而有所不同,却又保持其恒定不变的特性

    package object;
    
    class Poppet{
        private int i;
        Poppet(int ii){i = ii;}
    }
    public class BlankFinal{
        private final int i = 0; //Initialized final
        private final int j ; //blank final
        private final Poppet p; //Blank final reference
        //blank finals must be initialized in the constructor
        public BlankFinal(){
            j = 1; //initialized
            p = new Poppet(1);
        }
        public BlankFinal(int x)
        {
            j = x; //initialized final
            p = new Poppet(x); //initialized final reference
        }
        public static void main(String[] args)
        {
            new BlankFinal();
            new BlankFinal(47);
        }
    }//必须在域的定义出或每个构造器中用表达式对final赋值,这正是final域在使用前总是被初始化的原因所在

     final 参数

    java 允许参数列表中以声明的方式将参数指明为final,这意味着你无法再方法中改变参数所引用的对象

    //: ch7_19/final.java
    // blank final
    package object;
    
    class Gizmo{
        public void spin(){}
    }
    public class FinalArguments{
        void with(final Gizmo g)
        {
            //! g  = new Gizmo(); //Illegal  --g is final
        }
        void without(Gizmo g)
        {
            g = new Gizmo(); //ok -- g not final
            g.spin();
        }
        // void f(final int i) { i++;} //can't change 
        // you can only read from a final primitive
        int g(final int i){return i+1;}
        public static void main(String[] args)
        {
            FinalArguments bf = new FinalArguments();
            bf.without(null);
            bf.with(null);
        }
    }

    三 final 方法

    使用final 方法的原因有两个,第一个原因是把方法锁定,以防止任何继承类修改它的含义,这是出于设计的考虑:想要确保再继承中使方法行为保持不变,并且不会被覆盖

    过去使用final方法的第二个原因是效率,现在不用了,只有再明确禁止导出类的方法覆盖基类方法时,才将基类方法设置为final

    private和final:由于无法取得private方法,所以也就无法覆盖它,可以对private加final,但无意义

    //: reusing/FinalOverridingIllusion.java
    // it only loos like you cna override
    // a private or private final method
    package ch7_20;
    
    class WithFinals{
        //Identical to "private" alone
        private final void f(){
            System.out.println("WithFinals.f()");
        }
        private void g() {
            System.out.println("WithFinals.g()");
        }
    }
    
    class OverridePrivate extends WithFinals{
        private final void f()
        {
          System.out.println("Overridingprivate.f()");
        }
        private void g()
        {
            System.out.println("Overridingprivate.g()");
        }
    }
    
    class OverridePrivate2 extends OverridePrivate{
        public final void f()
        {
          System.out.println("Overridingprivate2.f()"); //"覆盖" 只有在某方法时接口的一部分才会出现
        }
        public void g()
        {
            System.out.println("Overridingprivate2.g()");
        }
    }
    public class FinalOverridingIllusion{
        public static void main(String[] args)
        {
            OverridePrivate2 op2 = new OverridePrivate2();
            op2.f();
            op2.g();
            // you can upcast
            OverridePrivate op = op2;
            // but you can't call the methods
            //! op.f();
            //! op.g();
            WithFinals wf = op2;
            //! wf.f();
            //! wf.g();
        }
    }

    final 类

    当将某个类的整体定义为final时,就表明了 你不打算继承该类,而且也不允许别人这样做,

    package object;
    
    class SmallBrain{
        
    }
    final class Dinosaur{
        int i = 7; //Dinosaur 所有方法都隐式的指定为是final的
        int j = 1;
        
        SmallBrain x = new SmallBrain();
        void f(){}
    }
    // class further extends dinosaur {}
    // error: annt extend final class Dinosaur
    public class Jurassic{
        public static void main(String[] args)
        {
            Dinosaur n = new Dinosaur();
            n.f();
            n.i =40;
            n.j++;
        }
    }

    在设计类时将方法指明时final,应该说时明智的.

  • 相关阅读:
    《瓦尔登湖》读书随笔
    Ubuntu下nginx+uwsgi+flask的执行环境搭建
    Android studio SweetAlert for Android
    mysql 主从不同步处理--数据库初始化
    Nginx学习——http配置项解析编程
    支付宝集分宝接口开发的相关问题解答
    解读刘强东关于人才的两个标准和5个层次
    oc35--自定义构造方法
    oc34--instancetype和id的区别
    oc33--构造方法2
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/10193454.html
Copyright © 2020-2023  润新知