final关键字的几种用法
在java的关键字中,static和final是两个我们必须掌握的关键字。不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构。下面我们来了解一下final关键字及其用法。
final关键字
在java中,final的含义在不同的场景下有细微的差别,但总体上来说,它指的是“这是不可变的”。下面,我们来讲final的四种主要用法。
1.修饰数据
在编写程序时,我们经常需要说明一个数据是不可变的,我们成为常量。在java中,用final关键字修饰的变量,只能进行一次赋值操作,并且在生存期内不可以改变它的值。更重要的是,final会告诉编译器,这个数据是不会修改的,那么编译器就可能会在编译时期就对该数据进行替换甚至执行计算,这样可以对我们的程序起到一点优化。不过在针对基本类型和引用类型时,final关键字的效果存在细微差别。我们来看下面的例子:
class Value {
int v;
public Value(int v) {
this.v = v;
}
} public class FinalTest { final int f1 = 1;
final int f2;
public FinalTest() {
f2 = 2;
} public static void main(String[] args) {
final int value1 = 1;
// value1 = 4;
final double value2;
value2 = 2.0;
final Value value3 = new Value(1);
value3.v = 4;
}
}
上面的例子中,我们先来看一下main方法中的几个final修饰的数据,在给value1赋初始值之后,我们无法再对value1的值进行修改,final关键字起到了常量的作用。从value2我们可以看到,final修饰的变量可以不在声明时赋值,即可以先声明,后赋值。value3时一个引用变量,这里我们可以看到final修饰引用变量时,只是限定了引用变量的引用不可改变,即不能将value3再次引用另一个Value对象,但是引用的对象的值是可以改变的,从内存模型中我们看的更加清晰:
上图中,final修饰的值用粗线条的边框表示它的值是不可改变的,我们知道引用变量的值实际上是它所引用的对象的地址,也就是说该地址的值是不可改变的,从而说明了为什么引用变量不可以改变引用对象。而实际引用的对象实际上是不受final关键字的影响的,所以它的值是可以改变的。
另一方面,我们看到了用final修饰成员变量时的细微差别,因为final修饰的数据的值是不可改变的,所以我们必须确保在使用前就已经对成员变量赋值了。因此对于final修饰的成员变量,我们有且只有两个地方可以给它赋值,一个是声明该成员时赋值,另一个是在构造方法中赋值,在这两个地方我们必须给它们赋初始值。
最后我们需要注意的一点是,同时使用static和final修饰的成员在内存中只占据一段不能改变的存储空间。
2.修饰方法参数
前面我们可以看到,如果变量是我们自己创建的,那么使用final修饰表示我们只会给它赋值一次且不会改变变量的值。那么如果变量是作为参数传入的,我们怎么保证它的值不会改变呢?这就用到了final的第二种用法,即在我们编写方法时,可以在参数前面添加final关键字,它表示在整个方法中,我们不会(实际上是不能)改变参数的值:
public class FinalTest { /* ... */ public void finalFunc(final int i, final Value value) {
// i = 5; 不能改变i的值
// v = new Value(); 不能改变v的值
value.v = 5; // 可以改变引用对象的值
}
}
3.修饰方法
第三种方式,即用final关键字修饰方法,它表示该方法不能被覆盖。这种使用方式主要是从设计的角度考虑,即明确告诉其他可能会继承该类的程序员,不希望他们去覆盖这个方法。这种方式我们很容易理解,然而,关于private和final关键字还有一点联系,这就是类中所有的private方法都隐式地指定为是final的,由于无法在类外使用private方法,所以也就无法覆盖它。
4.修饰类
了解了final关键字的其他用法,我们很容易可以想到使用final关键字修饰类的作用,那就是用final修饰的类是无法被继承的。
上面我们讲解了final的四种用法,然而,对于第三种和第四种用法,我们却甚少使用。这不是没有道理的,从final的设计来讲,这两种用法甚至可以说是鸡肋,因为对于开发人员来讲,如果我们写的类被继承的越多,就说明我们写的类越有价值,越成功。即使是从设计的角度来讲,也没有必要将一个类设计为不可继承的。Java标准库就是一个很好的反例,特别是Java 1.0/1.1中Vector类被如此广泛的运用,如果所有的方法均未被指定为final的话,它可能会更加有用。如此有用的类,我们很容易想到去继承和重写他们,然而,由于final的作用,导致我们对Vector类的扩展受到了一些阻碍,导致了Vector并没有完全发挥它应有的全部价值。
总结
final关键字是我们经常使用的关键字之一,它的用法有很多,但是并不是每一种用法都值得我们去广泛使用。它的主要用法有以下四种:
- 用来修饰数据,包括成员变量和局部变量,该变量只能被赋值一次且它的值无法被改变。对于成员变量来讲,我们必须在声明时或者构造方法中对它赋值;
- 用来修饰方法参数,表示在变量的生存期中它的值不能被改变;
- 修饰方法,表示该方法无法被重写;
- 修饰类,表示该类无法被继承。
上面的四种方法中,第三种和第四种方法需要谨慎使用,因为在大多数情况下,如果是仅仅为了一点设计上的考虑,我们并不需要使用final来修饰方法和类。
final关键字的几种用法的更多相关文章
- 【转载】java final 关键字的几种用法
原文链接点这里,感谢博主分享 在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构 ...
- [java]final关键字的几种用法
在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.下面我们来了解一下final ...
- .NET(c#)new关键字的三种用法
前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...
- NEW关键字的三种用法
最近面试中有一道题是写new关键字的几种用法,想了下写下我知道的两种用法 第一种 创建对象.调用构造函数,这就不用讲了 ClassA A=new ClassA(); 第二种 是作为修饰符,显示隐藏继 ...
- 【转载】java static 关键字的四种用法
原文链接点这里,感谢博主分享 在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构 ...
- [java]static关键字的四种用法
在java的关键字中,static和final是两个我们必须掌握的关键字.不同于其他关键字,他们都有多种用法,而且在一定环境下使用,可以提高程序的运行性能,优化程序的结构.下面我们先来了解一下stat ...
- c# new关键字的三种用法
三种用法如下: 在 C# 中,new 关键字可用作运算符.修饰符或约束. 1)new 运算符:用于创建对象和调用构造函数. 2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成 ...
- java中 this 关键字的三种用法
Java中this的三种用法 调用属性 (1)this可以调用本类中的任何成员变量 调用方法(可省略) (2)this调用本类中的成员方法(在main方法里面没有办法通过this调用) 调用构造方法 ...
- Static 关键字的 5 种用法,你会几种?
); System.out.println(Thread.currentThread().getName() ...
随机推荐
- css margin使用技巧
margin使用技巧: (1)设置元素水平居中:margin:x auto; (2)margin负值让元素位移及边框合并 水平居中:auto 代码: <!DOCTYPE html> < ...
- vue_源码 原理 剖析
相关基础知识点 // 可以让 任意函数/方法 成功临时指定成对象的方法进行调用 - call/apply // 1. 根据伪数组生成 真数组 const lis = document.getEleme ...
- pheatmap, gplots heatmap.2和ggplot2 geom_tile实现数据聚类和热图plot
主要步骤 pheatmap 数据处理成矩阵形式,给行名列名 用pheatmap画热图(pheatmap函数内部用hclustfun 进行聚类) ggplot2 数据处理成矩阵形式,给行名列名 hclu ...
- css边框渐变
在实际开发中,我们经常遇见边框需要背景渐变的实现要求,那么如何去实现呢,今天给大家分享依稀几种情况 1.直角的背景渐变 <!DOCTYPE html> <html lang=&quo ...
- ThinkPHP5 添加多个文字水印及疑难解答
public function imageload() { $imgpath = ROOT_PATH . 'public' . DS . 'static' . DS . 'www' . DS . 'i ...
- mysql 储存过程
存储过程如同一门程序设计语言,同样包含了数据类型.流程控制.输入和输出和它自己的函数库. --------------------基本语法-------------------- 一.创建存储过程cr ...
- hydra用法
三.Syntax # hydra [[[-l LOGIN|-L FILE] [-p PASS|-P FILE]] | [-C FILE]] [-e ns] [-o FILE] [-t TASKS] [ ...
- flask基础一
一:flask认知 flask 短小精悍,可扩展强 flask 所有扩展的网址,flask.pocoo.org/externsions 有别于其他的web框架的地方:flask做了一个上下文管理机制 ...
- Xposed 在android 6.0上报couldn't load class,找不到xposed_init中配置的入口类
经测试再android 4.4时是可以直接在android studio中运行debug签名包,在xposed中运行的,但是6.0的机器不好使.解决办法是在运行时使用release版并签名 apply ...
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/maven/cli/MavenCli : Unsupported major.minor version 51.0
原因:JDK版本不兼容.运行的Java Class文件采用高版本的JDK编译,然后在低版本的JRE环境中运行,有时会报此错误. 解决:1)升级JDK 2)调整Eclipse中Java Compiler ...