zoukankan      html  css  js  c++  java
  • Java基础知识详解:final修饰符

    @author:Tobin
    水平有限,如有错误,望请斧正。
    参考《Java核心技术卷-基础知识第10版》
    https://blog.csdn.net/sinat_38899160/article/details/72650686


    本节讨论final修饰符的使用。
    final顾名思义有最终的含义,通过几个问答解释final的奥义。

    Q1:final修饰基本类型域

    回顾下基本类型。

    A:被final修饰的实例域,构建对象时必须初始化这样的实例域,也就是说,必须确保在每一个构造器执行之后,这个域的值被设置,并且在后面的操作中,不能够再对它进行修改。下面代码中的E变量就是被final修饰的而必须初始化的实例。
    除了实例类型,final还被用来修饰局部变量和静态变量。关于final修饰static变量,放到static中讲解。
    放到static中详解。
    修饰static变量即静态变量时,此时这样的变量又被称为静态常量,静态常量是属于类的,而不是属于对象,即可以直接利用类名访问静态常量,它被所有对象共有,即1000个对象可以有1000个S(下面代码中的字符串)拷贝,但是只会有1个C,即使没有声明任何对象,C也是存在的。比如Math类中的Math.PI。

    package test;
    
    public class Employee { 
        private final String S="final实例变量S"; 
        private final int A=100; 
        public final int B=90; 
        public static final int C=80; 
        private static final int D=70; 
        public final int E; //final空白,必须在初始化对象的时候赋初值 
        public Employee(int x){ 
        E=x; 
        } 
        /** 
        * @param args 
        */ 
        public static void main(String[] args) { 
            Employee t=new Employee(2); 
            //t.A=101; //出错,final变量的值一旦给定就无法改变 
            //t.B=91; //出错,final变量的值一旦给定就无法改变 
            //t.C=81; //出错,final变量的值一旦给定就无法改变 
            //t.D=71; //出错,final变量的值一旦给定就无法改变 
            System.out.println(t.A); 
            System.out.println(t.B); 
            System.out.println(t.C); //不推荐用对象方式访问静态字段 
            System.out.println(t.D); //不推荐用对象方式访问静态字段 
            System.out.println(Employee.C); 
            System.out.println(Employee.D); 
            //System.out.println(Employee.E); //出错,因为E为final空白,依据不同对象值有所不同. 
            System.out.println(t.E); 
            Employee t1=new Employee(3); 
            System.out.println(t1.E); //final空白变量E依据对象的不同而不同 
            } 
            private void test(){ 
            System.out.println(new Employee(1).A); 
            System.out.println(Employee.C); 
            System.out.println(Employee.D); 
            } 
            public void test2(){ 
            final int a; //final空白,在需要的时候才赋值 
            final int b=4; //局部常量--final用于局部变量的情形 
            final int c; //final空白,一直没有给赋值. 
            a=3; 
            //a=4; 出错,已经给赋过值了. 
            //b=2; 出错,已经给赋过值了. 
            } 
    }
    

    在构造Employee对象时,需要初始化。如果不写构造函数,编译器会直接报错,如果在构建对象时,不传入参数,一样会报错。

    Q2:final修饰方法

    A:被final修饰的方法不能够被继承。如下,当我们要改写f2函数的时候会报错。final修饰方法的一个好处是可以提高运行效率,编译器遇到final方法会转入内嵌机制(推荐博文https://blog.csdn.net/Java_I_ove/article/details/76946598),具体是如何提高的,放到以后学习JVM再研究。

    // Test1.java
    package test;
    public class Test1 {
        public void f1()
        {
            System.out.println("this is f1 from Test1");
        }
        
        public final void f2()
        {
            System.out.println("this is f2 from Test1");
        }
    }
    
    // Test2.java
    package test;
    
    public class Test2 extends Test1{
    
        public void f1()
        {
            System.out.println("this is f1 from Test1");
        }
        
        public void f2() //这里会报错
        {
            System.out.println("this is f2 from Test1");
        }
    
    }
    

    我们会很自然地联想到,Java中的构造函数可以被final修饰吗?在构造函数前面加final修饰符,编译器会直接报错。结论是不可以的。首先父类的构造函数不是成员函数,是不能够被继承的,但是可以被子类调用,既然不能被继承,也就不可以被重写。那么final修饰构造函数也就没有任何意义。至于构造函数在继承中是如何运行的,留到其它章节去研究(推荐博文https://blog.csdn.net/yuxiaohui78/article/details/43887373,https://blog.csdn.net/qiumengchen12/article/details/44829907)。

    A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.
    来源: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

    Q3:final修饰类

    final修饰的类是不可以被继承的。比如常见的string类。当给类加上final修饰后,类内的方法加不加final都是不可以被重写的。

    Q4:final修饰参数

    final修饰传入方法的参数时,该参数只读,不可以修改。

    Q5:final修饰对象

    final修饰对象时,不可以再指向其它的对象,但是对象的内容是可以修改的。

            final Employee a = new Employee(2);
            Employee b = new Employee(3);
            a.temp = 2;//可以执行,final指向的对象不允许改变,但是可以修改对象的内容
            b = a;//可以执行,b并未声明final
            a = b;//出错,final指向的对象不允许更换
    
  • 相关阅读:
    iOS 字典转模型 KVC 实现
    iOS开发 滤镜的使用
    iOS开发 二维码生成
    iOS开发 iOS10兼容访问http
    Jmockit 使用小计 1.46
    springboot样例 pom与小花招
    react + antd html网页配置非框架
    Vue 设置 vue router 路径错误检查
    java 8 读取配置文件例子
    mysql 项目配置
  • 原文地址:https://www.cnblogs.com/zuotongbin/p/11080592.html
Copyright © 2011-2022 走看看