zoukankan      html  css  js  c++  java
  • 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,应该说时明智的.

  • 相关阅读:
    Oracle 推出 ODAC for Entity Framework 和 LINQ to Entities Beta版
    Entity Framework Feature CTP 5系列文章
    MonoDroid相关资源
    MSDN杂志上的Windows Phone相关文章
    微软学Android Market推出 Web Windows Phone Marketplace
    使用 Visual Studio Agent 2010 进行负载压力测试的安装指南
    MonoMac 1.0正式发布
    Shawn Wildermuth的《Architecting WP7 》系列文章
    使用.NET Mobile API即51Degrees.mobi检测UserAgent
    MongoDB 客户端 MongoVue
  • 原文地址:https://www.cnblogs.com/jiangfeilong/p/10193454.html
Copyright © 2011-2022 走看看