前言

在C#经典面试中掺杂过Java的final关键字,主要用于类不能被继承,在C#则是利用关键字seal修饰类为密封类,而在Java中的final关键字的具体用法包含C#中const、readonly、seal三者使用之和,本节我们来聊聊Java的关键字final。

关键字final

通过final关键字修饰意为无法改变,在Java早期版本通过final可以改善性能或者提高效率,但现如今版本final已经无所谓性能,我们只关注于在设计时应用final的具体场景,final关键字包含两层含义:其一,编译时常量不变,其二,运行时初始化值而后不被改变。这两者其实就是C#中的const和readonly关键字的使用。 final主要用于三种情况,修饰数据、方法、类,但本质上都是表示不可变,至于“不可变”的含义就看对应哪种场景。当然加上static修饰符只是表明在内存中只保存一份数据,这里我们就不做过多探讨。

数据

编译时常量和C#中概念一致,只不过C#用const修饰,同时对于变量的命名都是采用大写方式,单词与单词之间用下划线隔开,比如如下编译时常量

public final int VALUE_ONE = 1;

上述已经说过,final不仅仅只是对于编译时必须为常量,还可以用于运行时初始化时的值,比如通过随机函数生成值

public  static Random random = new Random();

public final int VALUE_ONE = random.nextInt(20);

这种运行时初始化值方式就是C#中的readonly,如下:

public static Random random = new Random();

public readonly int VALUE_ONE = random.Next();

对于C#中的readonly初始值,我们知道除了在定义时赋值,也可以在构造函数中初始化值,若是再加上static,很显然必须在静态构造函数中初始化

class Program
{
public readonly int VALUE_ONE; public Program()
{
VALUE_ONE = ;
}
}

final关键字同样也能达到上述使用readonly的效果,只不过在Java中称其为“空白final”,所谓空白final是指被声明为final但未给定初始值,但是无论何种情况,编译器必须确保在使用数据之前必须进行初始化

public class Main {

    public final int VALUE_ONE;

    public Main() {
VALUE_ONE = 1;
}
}

参数

无论是作为方法参数还是作为初始化变量的修饰,我们可以更改该参数里面的值,但是无法更改参数引用所指向的对象。如下示例为修饰初始化类变量,作为方法参数同理,这里不再阐述。

class Value {
int i; public Value(int i) {
this.i = i;
}
} public class FinalDemo {
public final Value value = new Value(1);
}
public class Main {

    public static void main(String[] args) {

        FinalDemo finalDemo = new FinalDemo();

        //可以更改final参数里的值
finalDemo.value.i = 2; //不能更改参数所指向的对象(编译报错)
finalDemo.value = new Value(2);
}
}

方法

final修饰方法是将方法进行锁定,以防止任何继承类修改它本身的含义,此意为用以标记该方法不能被覆盖(对于对象范围内)或隐藏,这为后续开发人员创建其方法所在类的子类无法覆盖其行为提供有力的保证。比如如下计数器则是一个很好的例子

public class Counter {
private int counter = 0; public final int count() {
return ++counter;
} public final int reset() {
return (counter = 0);
}
}

但是我们去掉上述count方法的修饰符,进行如下操作,很显然将破坏原始方法的行为,打印出结果为2

Counter c = new Counter() {
public int count() {
super.count();
return super.count();
}
};
System.out.println(c.count());

若将整个类定义为final时,这说明此类将不会被继承和C#中seal修饰符如出一辙,或出于安全考虑,或出于设计已确定该类不会再做任何变动,不希望该类有子类

public final class Counter {
} //编译发生错误
class SubCounter extends Counter {
}

总结

本节我们详细讲解了final关键字,该关键字是C#中const、readonly、seal三者使用的组合,Java编程思想虽然将其划分为数据、方法、类,这里我认为划分为变量(包含数据和参数)、方法、类更合理。其实语法都大同小异,还是那句话,学习的本质在于归纳总结并举一反三从而内化。

Java入门系列之final的更多相关文章

  1. Java入门系列-26-JDBC

    认识 JDBC JDBC (Java DataBase Connectivity) 是 Java 数据库连接技术的简称,用于连接常用数据库. Sun 公司提供了 JDBC API ,供程序员调用接口和 ...

  2. Java入门系列-19-泛型集合

    集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足. 如果并不知道程序运行时会需要多少对象,或者需要更复杂方式存储对象,可以使用Java集合框架. Java 集合框架提 ...

  3. Java入门系列之重写

    前言 关于所有Java系列文章面向有一定基础的童鞋,所写每一篇希望有一定含金量,有些内容可能会从Java整个语法全局考虑穿插后续要讲解的内容以成系统,若不理解,请看完后再学习.上一节我们讲解完了fin ...

  4. Java入门系列:实例讲解ArrayList用法

    本文通过实例讲解Java中如何使用ArrayList类. Java.util.ArrayList类是一个动态数组类型,也就是说,ArrayList对象既有数组的特征,也有链表的特征.可以随时从链表中添 ...

  5. Java入门系列(四)内部类

    为什么需要内部类? 真正的原因是这样的,java中的内部类和接口加在一起,可以的解决常被C++程序员抱怨java中存在的一个问题没有多继承.实际上,C++的多继承设计起来很复杂,而java通过内部类加 ...

  6. Java入门系列(二)Java常用关键字

    53个关键字 在JAVA中目前一共有53个关键字:其中由51+2个保留字=53个关键字 访问控制 private protected public default              类.方法和 ...

  7. Java入门系列-18-抽象类和接口

    抽象类 在第16节继承中,有父类 People People people=new People(); people.sayHi(); 实例化People是没有意义的,因为"人"是 ...

  8. Java入门系列-16-继承

    这一篇文章教给新手学会使用继承,及理解继承的概念.掌握访问修饰符.掌握 final 关键字的用法. 继承 为什么要使用继承 首先我们先看一下这两个类: public class Teacher { p ...

  9. Java入门系列-14-深入类和对象

    这篇文章用大量的代码帮你搞懂:值传递和引用传递.构造方法.方法重载.static关键字的使用 方法参数传递-值传递和引用传递 1.值传递 敲一敲: /** * 使用方法交换两个变量的值 * @auth ...

随机推荐

  1. 本地配置gitee

    一 下载工具 Git-2.62.0-64-bit.exe 以上工具版本号不需要一样,安装完前两个后重新启动系统,再安装第3个. 二 码云网站注册 https://gitee.com/ 使用邮箱注册 注 ...

  2. 【网页设计】第四周 JavaSript

    第四周  JSP 一  JSP概述 含义: Java Server Pages, 广泛使用的服务器端脚本语言之一:(运行在服务器端  BS结构) 由服务器端的JSP引擎执行JSP代码,然后将结果以HT ...

  3. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  4. C#数据结构与算法系列(二):稀疏数组(SparseArray)

    1.介绍 当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组.    稀疏数组的处理方法是: 1.记录数组一共有几行几列,有多少个不同的值    2.把具有不同值的元素的 ...

  5. centos7下docker的安装教程

    Centos7下docker安装教程以及踩过的那些坑 推荐在Centos下安装docker,在windows下安装docker可能会遇到很多的问题,而且docker官方推荐使用linux环境来使用do ...

  6. nsswitch名称解析框架

    name service switch 名称解析框架(逻辑图) 让多种应用程序能灵活进行名称解析的通用框架 与各种类型存储进行交互的公共实现 规定通过哪些途径以及按照什么顺序通过这些途径来查找特定类型 ...

  7. NAT网络地址转化和DHCP

    DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)通常被应用在大型的局域网络环境中,主要作用是集中的管理.分配IP地址,使网络环境中的主机动态的获得I ...

  8. HashSet扩容机制在时间和空间上的浪费,远大于你的想象

    一:背景 1. 讲故事 自从这个纯内存项目进了大客户之后,搞得我现在对内存和CPU特别敏感,跑一点数据内存几个G的上下,特别没有安全感,总想用windbg抓几个dump看看到底是哪一块导致的,是我的代 ...

  9. [CentOS 7]挂载ntfs格式U盘

    在我们将U盘插入装有CentOS的系统时,经常会出现如图所示的错误提示.这是因为linux系统并不能兼容NTFS的文件系统.其解决方法如下(建议先进入root模式): 1.首先下载"ntfs ...

  10. 关于GridView的横向合并数据信息

    此为asp.net 运行展示: 前端代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehin ...