美文网首页
Java之final关键字

Java之final关键字

作者: RavenX | 来源:发表于2017-12-10 10:57 被阅读0次

    1.final关键字

    final关键字通常指的是“这是无法改变的的”。不想做出改变处于两种理由:设计或者效率。

    final关键字通常有三种分类:

    1. 数据
    2. 方法

    2.各种情况的介绍

    2.1final数据

    许多编程语言都有某种方法,来想编译器告知一块数据是恒定不变。有时数据的恒定不变是有很用的。比如:

    1. 一个永不改变的编译时常量
    2. 一个在运行时被初始化的值

    对于编译期常量这种情况,编译器可以将该常量值代入任何可能用到它的计算式中,也就是十,可以在编译时执行计算式,这旧情了一些运行时的负担。在Java中,这类常量必须是基本数据类型(int,boolean,float,double等)。在对这个常量进行定义的时候,必须对其进行赋值。对于对象引用,一旦被初始化后,无法在将引用重指向,但是可以更改这个对象的成员值。

    另外:一个既是static又是final 的字段只占据一段不能改变的存储空间,它必须在定义的时候进行赋值,否则编译器将不予通过。那么仅仅是final关键字修饰的字段需不要需要在定义的时候进行赋值呢?之后会给出答案。

    现在来看编译期常量和非编译期常量,如:

    public class Test {
        //编译期常量
        final int i = 1;
        final static int J = 1;
        final int[] a = {1,2,3,4};
        //非编译期常量
        Random r = new Random();
        final int k = r.nextInt();
        
        public static void main(String[] args) {
            
        }
    }
    
    

    k的值由随机数对象决定,所以不是所有的final修饰的字段都是编译期常量,只是k的值在被初始化后无法被更改。下面再来看一个有趣的代码:

    package learn;
    
    import java.util.Random;
    public class Test {
        static Random r = new Random();
        final int k = r.nextInt(10);
        static final int k2 = r.static nextInt(10); 
        public static void main(String[] args) {
            Test t1 = new Test();
            System.out.println("k="+t1.k+" k2="+t1.k2);
            Test t2 = new Test();
            System.out.println("k="+t2.k+" k2="+t2.k2);
        }
    }
    
    

    输出如下:

    k=2 k2=7
    k=8 k2=7
    

    我们可以发现对于不同的对象k的值是不同的,但是k2的值却是相同的,这是为什么呢?因为static关键字所修饰的字段并不属于一个对象,而是属于这个类的。也可简单的理解为static final所修饰的字段仅占据内存的一个一份空间,一旦被初始化之后便不会被更改。

    2.2 final参数

    Java允许在参数列表中以声明的方式将参数指明为final,这意味这你无法在方法中更改参数引用所指向的对象。这个特性主要用来向匿名内部类传递数据

    2.3 final和private

    类中所有private方法都隐式地指定为final的,由于无法取用private方法,所以也就不能覆盖它。可以对private方法增添final关键字,但这样做并没有什么好处。

    下面的代码也很有趣,说明了private是隐式的final

    package learn;
    
    public class Base {
    
        private void test() {
            
        }
        
    }
    
    
    public class Son extends Base{
    
        public void test() {
            
        }
        public static void main(String[] args) {
            Son son = new Son();
            Base father = son;
            //father.test();
        }
    }
    
    

    Base和Son都有方法test(),但是这并不是一种覆盖,因为private所修饰的方法是隐式的final,也就是无法被继承,所以更不用说是覆盖了,在Son中的test()方法不过是属于Son的新成员罢了,Son进行向上转型得到father,但是father.test()是不可执行的,因为Base中的test方法是private的,无法被访问到。

    2.4 final

    当某个类的整体定义为final时,就表明了你不能打算继承该类,而且也不允许别人这么做。即这个类是不能有子类的。

    注意:final类中的所有方法都隐式为final,因为无法覆盖他们,所以在final类中给任何方法添加final关键字是没有任何意义的。

    2.5 blank final

    Java允许生成空白final,也就是说被声明为final但又没有给出定值的字段,但是必须在该字段被使用之前被赋值,这给予我们两种选择:

    1. 在定义处进行赋值(这不叫空白final)
    2. 在构造器中进行赋值,保证了该值在被使用前赋值。

    这增强了final的灵活性。

    看下面代码:

    public class Test {
        final int i1 = 1;
        final int i2;//空白final
        public Test() {
            i2 = 1;
        }
        public Test(int x) {
            this.i2 = x;
        }
    }
    
    

    可以看到i2的赋值更为灵活。但是请注意,如果字段由static和final修饰,仅能在定义处赋值,因为该字段不属于对象,属于这个类。

    相关文章

      网友评论

          本文标题:Java之final关键字

          本文链接:https://www.haomeiwen.com/subject/osqmixtx.html