目录

  • Java开发入门
    • ● Java 概述
    • ● JDK的使用
    • ● 系统环境变量
    • ● 第一个Java程序
    • ● Java的运行机制
    • ● 教学设计
    • ● 课程讲义
    • ● 案例学习
    • ● 课后题答案
  • Java 编程基础
    • ● Java的基本语法
      • ● Java代码基本格式
      • ● Java中的注释
      • ● Java中的关键字
      • ● Java中的标识符
    • ● Java中的变量与常量
      • ● 变量的定义
      • ● 变量的数据类型
        • ● 案例导学
      • ● 变量的类型转换
        • ● 案例导学-自动类型转换
        • ● 案例导学-强制类型转换
      • ● 变量的作用域
        • ● 案例导学-作用域
      • ● Java中的常量
    • ● Java中的运算符
      • ● 案例导学-算术运算符
      • ● 案例导学-赋值运算符
      • ● 案例导学-比较运算符
      • ● 案例导学-逻辑运算符
      • ● 案例导学-位运算符
      • ● 案例导学-运算符的优先级
    • ● 选择结构语句
      • ● 案例导学-if条件语句
      • ● 案例导学-switch条件语句
    • ● 循环结构语句
      • ● 案例导学-while循环语句
      • ● 案例导学-for循环语句
      • ● 案例导学-循环嵌套
      • ● 案例导学-break语句
      • ● 案例导学-continue语句
    • ● 数组
      • ● 案例导学-一维数组的定义
      • ● 案例导学-数组最值
      • ● 案例导学-数组排序
    • ● 教学设计
    • ● 课程讲义
    • ● 课后题答案
  • 面向对象(上)
    • ● 面向对象概述
    • ● Java中的类与对象
      • ● 案例导学-类与对象
    • ● 类的封装
    • ● 案例导学-类的封装
    • ● 方法的重载和递归
    • ● 构造方法
      • ● 案例导学-构造方法与重载
    • ● this关键字
      • ● 案例导学-this
    • ● static关键字
      • ● 案例导学-静态变量
      • ● 案例导学-静态方法
      • ● 案例导学-静态代码块
    • ● 教学设计
    • ● 课程讲义
    • ● 章节测试
    • ● 课后题答案
  • 面向对象(下)
    • ● 类的继承
      • ● 案例导学-类的继承
      • ● 案例导学-方法的重写
      • ● 案例导学-super访问父类成员变量
      • ● 案例导学-super访问父类成员方法
      • ● 案例导学-super访问父类构造方法
    • ● final关键字
    • ● 抽象类和接口
    • ● 多态
    • ● 内部类
    • ● JDK8的Lambda表达式
    • ● 异常
    • ● 垃圾回收
    • ● 教学设计
    • ● 课程讲义
    • ● 章节测试
    • ● 课后习题答案
  • Java中的常用类
    • ● String类和StringBuffer类
    • ● System类与Runtime类
    • ● Math类与Random类
    • ● 包装类
    • ● 日期与时间类
    • ● 格式化类
    • ● 课后题答案
    • ● 课程讲义
  • 集合
    • ● 集和概述
    • ● Collection接口
    • ● List接口
      • ● List接口简介
      • ● ArrayList集合
      • ● LinkList集合
    • ● Collection集合遍历
    • ● Set接口
    • ● Map接口
    • ● 泛型
    • ● 常用工具类
      • ● Collections工具类
      • ● Arrays工具类
    • ● 课后题参考答案
    • ● 课程讲义
  • IO流
    • ● I/O流概述
    • ● 字节流
    • ● 字符流
    • ● File类
    • ● RandomAccessFile
    • ● 对象序列化
    • ● NIO
    • ● NIO.2
    • ● 课后题答案
    • ● 课程讲义
    • ● 章节测试
  • GUI(图形用户接口)
    • ● Swing概述
    • ● Swing顶级容器
    • ● 布局管理器
    • ● 事件处理
    • ● Swing常用组件
    • ● Swing组件的整合使用
    • ● JavaFX图形用户界面工具
    • ● 课程讲义
  • JDBC
    • ● 什么是JDBC
    • ● JDBC常用API
    • ● JDBC编程
    • ● 案例-使用JDBC实现QQ登录
    • ● 课程讲义
  • 多线程
    • ● 线程概述
    • ● 线程的创建
    • ● 线程的生命周期及状态转换
    • ● 线程的调度
    • ● 多线程同步
    • ● 多线程通信
    • ● 教学设计
    • ● 课后题参考答案
    • ● 课程讲义
  • 网络编程
    • ● 网络通信协议
    • ● UDP通信
    • ● TCP通信
    • ● 课程讲义
  • Eclipse开发工具
    • ● Eclipse概述
    • ● Eclipse的安装与启动
    • ● Eclipse进行程序开发
    • ● Eclipse程序调试
    • ● 使用Eclipse导出、导入jar文件
  • ACM大赛题库
    • ● 2027
    • ● 2028
    • ● 2024-2026
    • ● 2012-2023
    • ● 2018-2020
    • ● 2015-2017
    • ● 2012-2014
    • ● 2009-2011
    • ● 2003-2005
    • ● 2000-2002
  • PBL学生风采展示
    • ● 实验一
    • ● 实验二
    • ● 实验三
    • ● 实验四
final关键字

一.final关键字的基本用法


在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。下面就从这三个方面来了解一下final关键字的基本用法。

  1.修饰类

  当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。final类中的成员变量可以根据需要设为final,但是要注意final类中的所有成员方法都会被隐式地指定为final方法。

在使用final修饰类的时候,要注意谨慎选择,除非这个类真的在以后不会用来继承或者出于安全的考虑,尽量不要将类设计为final类。

  2.修饰方法

  “使用final方法的原因有两个。第一个原因是把方法锁定,以防任何继承类修改它的含义;第二个原因是效率。在早期的Java实现版本中,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升。在最近的Java版本中,不需要使用final方法进行这些优化了。”

—————————《Java编程思想》第四版第143页

  因此,如果只有在想明确禁止 该方法在子类中被覆盖的情况下才将方法设置为final的。

  注:类的private方法会隐式地被指定为final方法。

  3.修饰变量

  修饰变量是final用得最多的地方,也是本文接下来要重点阐述的内容。首先了解一下final变量的基本语法:

  对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。

二.深入理解final关键字

  在了解了final关键字的基本用法之后,这一节我们来看一下final关键字容易混淆的地方。

1.类的final变量和普通变量有什么区别?

  当用final作用于类的成员变量时,成员变量(注意是类的成员变量,局部变量只需要保证在使用之前被初始化赋值即可)必须在定义时或者构造器中进行初始化赋值,而且final变量一旦被初始化赋值之后,就不能再被赋值了。

  那么final变量和普通变量到底有何区别呢?下面请看一个例子:

public class Test {
    public static void main(String[] args)  {
        String a = "hello2"
        final String b = "hello";
        String d = "hello";
        String c = b + 2
        String e = d + 2;
        System.out.println((a == c));
        System.out.println((a == e));
    }
}

运行结果:

true
false

public class Test {
    public static void main(String[] args)  {
        String a = "hello2";  
        final String b = getHello();
        String c = b + 2;  
        System.out.println((a == c));
 
    }
     
    public static String getHello() {
        return "hello";
    }
}
运行结果:false
2.被final修饰的引用变量指向的对象内容可变吗?
  在上面提到被final修饰的引用变量一旦初始化赋值之后就不能再指向其他的对象,那么该引用变量指向的对象的内容可变吗?看下面这个例子:
  public class Test {

    public static void main(String[] args)  {

        final MyClass myClass = new MyClass();

        System.out.println(++myClass.i);
    }

}
class MyClass {
    public int i = 0;
}
3.final和static
  很多时候会容易把static和final关键字混淆,static作用于成员变量用来表示只保存一份副本,而final的作用是用来保证变量不可变。
  public class Test {
   public static void main(String[] args)  {
       MyClass myClass1 = new MyClass();
       MyClass myClass2 = new MyClass();
       System.out.println(myClass1.i);
       System.out.println(myClass1.j);
       System.out.println(myClass2.i);
       System.out.println(myClass2.j);

   }
}

class MyClass {
   public final double i = Math.random();
   public static double j = Math.random();
}
由运行结果可知:两个j值都是一样的,而i的值却是不同的。

三、final的重要知识点

final关键字可以用于成员变量、本地变量、方法以及类。
final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误。
你不能够对final变量再次赋值。
本地变量必须在声明时赋值。
在匿名类中所有变量都必须是final变量。
final方法不能被重写。
final类不能被继承。
final关键字不同于finally关键字,后者用于异常处理。
final关键字容易与finalize()方法搞混,后者是在Object类中定义的方法,是在垃圾回收之前被JVM调用的方法。
接口中声明的所有变量本身是final的。
final和abstract这两个关键字是反相关的,final类就不可能是abstract的。
final方法在编译阶段绑定,称为静态绑定(static binding)。
没有在声明时初始化final变量的称为空白final变量(blank final variable),它们必须在构造器中初始化,或者调用this()初始化。不这么做的话,编译器会报错“final变量(变量名)需要进行初始化”。
将类、方法、变量声明为final能够提高性能,这样JVM就有机会进行估计,然后优化。
按照Java代码惯例,final变量就是常量,而且通常常量名要大写:
private final int COUNT = 10;