final 在 Java 中的意思是最终,也可以称为完结器,表示对象是最终形态的,不可改变的意思。final 应用于类、方法和变量时意义是不同的,但本质是一样的,都表示不可改变,类似 C# 里的 sealed 关键字。
使用 final 关键字声明类、变量和方法需要注意以下几点:
final 修饰的变量即成为常量,只能赋值一次,但是 final 所修饰局部变量和成员变量有所不同。
注意:final 修饰的变量不能被赋值这种说法是错误的,严格的说法是,final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。
public class FinalDemo {
void doSomething() {
// 没有在声明的同时赋值
final int e;
// 只能赋值一次
e = 100;
System.out.print(e);
// 声明的同时赋值
final int f = 200;
}
// 实例常量
final int a = 5; // 直接赋值
final int b; // 空白final变量
// 静态常量
final static int c = 12;// 直接赋值
final static int d; // 空白final变量
// 静态代码块
static {
// 初始化静态变量
d = 32;
}
// 构造方法
FinalDemo() {
// 初始化实例变量
b = 3;
// 第二次赋值,会发生编译错误
// b = 4;
}
}
上述代码第 4 行和第 6 行是声明局部常量,其中第 4 行只是声明没有赋值,但必须在使用之前赋值(见代码第 6 行),其实局部常量最好在声明的同时初始化。
代码第 13、14、16 和 17 行都声明成员常量。代码第 13 和 14 行是实例常量,如果是空白 final 变量(见代码第 14 行),则需要在构造方法中初始化(见代码第 27 行)。
代码第 16 和 17 行是静态常量,如果是空白 final 变量(见代码第 17 行),则需要在静态代码块中初始化(见代码第 21 行)。
另外,无论是那种常量只能赋值一次,见代码第 29 行为 b 常量赋值,因为之前 b 已经赋值过一次,因此这里会发生编译错误。
final 修饰基本类型变量和引用类型变量的区别
当使用 final 修饰基本类型变量时,不能对基本类型变量重新赋值,因此基本类型变量不能被改变。 但对于引用类型变量而言,它保存的仅仅是一个引用,final 只保证这个引用类型变量所引用的地址不会改变,即一直引用同一个对象,但这个对象完全可以发生改变。
下面程序示范了 final 修饰数组和 Person 对象的情形。
import java.util.Arrays;
class Person {
private int age;
public Person() {
}
// 有参数的构造器
public Person(int age) {
this.age = age;
}
// 省略age的setter和getter方法
// age 的 setter 和 getter 方法
}
public class FinalReferenceTest {
public static void main(String[] args) {
// final修饰数组变量,iArr是一个引用变量
final int[] iArr = { 5, 6, 12, 9 };
System.out.println(Arrays.toString(iArr));
// 对数组元素进行排序,合法
Arrays.sort(iArr);
System.out.println(Arrays.toString(iArr));
// 对数组元素赋值,合法
iArr[2] = -8;
System.out.println(Arrays.toString(iArr));
// 下面语句对iArr重新赋值,非法
// iArr = null;
// final修饰Person变量,p是一个引用变量
final Person p = new Person(45);
// 改变Person对象的age实例变量,合法
p.setAge(23);
System.out.println(p.getAge());
// 下面语句对P重新赋值,非法
// p = null;
}
}
从上面程序中可以看出,使用 final 修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。
例如上面 iArr 变量所引用的数组对象,final 修饰后的 iArr 变量不能被重新赋值,但 iArr 所引用数组的数组元素可以被改变。
与此类似的是,p 变量也使用了 final 修饰,表明 p 变量不能被重新赋值,但 p 变量所引用 Person 对象的成员变量的值可以被改变。
注意:在使用 final 声明变量时,要求全部的字母大写,如 SEX,这点在开发中是非常重要的。
如果一个程序中的变量使用 public static final 声明,则此变量将称为全局变量,如下面的代码:
public static final String SEX= "女";
final 修饰的方法不可被重写,如果出于某些原因,不希望子类重写父类的某个方法,则可以使用 final 修饰该方法。
Java 提供的 Object 类里就有一个 final 方法 getClass(),因为 Java 不希望任何类重写这个方法,所以使用 final 把这个方法密封起来。但对于该类提供的 toString() 和 equals() 方法,都允许子类重写,因此没有使用 final 修饰它们。
下面程序试图重写 final 方法,将会引发编译错误。
public class FinalMethodTest {
public final void test() {
}
}
class Sub extends FinalMethodTest {
// 下面方法定义将出现编译错误,不能重写final方法
public void test() {
}
}
上面程序中父类是 FinalMethodTest,该类里定义的 test() 方法是一个 final 方法,如果其子类试图重写该方法,将会引发编译错误。
对于一个 private 方法,因为它仅在当前类中可见,其子类无法访问该方法,所以子类无法重写该方法——如果子类中定义一个与父类 private 方法有相同方法名、相同形参列表、相同返回值类型的方法,也不是方法重写,只是重新定义了一个新方法。
因此,即使使用 final 修饰一个 private 访问权限的方法,依然可以在其子类中定义与该方法具有相同方法名、相同形参列表、相同返回值类型的方法。
下面程序示范了如何在子类中“重写”父类的 private final 方法。
public class PrivateFinalMethodTest {
private final void test() {
}
}
class Sub extends PrivateFinalMethodTest {
// 下面的方法定义不会出现问题
public void test() {
}
}
上面程序没有任何问题,虽然子类和父类同样包含了同名的 void test() 方法,但子类并不是重写父类的方法,因此即使父类的 void test() 方法使用了 final 修饰,子类中依然可以定义 void test() 方法。
final 修饰的方法仅仅是不能被重写,并不是不能被重载,因此下面程序完全没有问题。
public class FinalOverload {
// final 修饰的方法只是不能被重写,完全可以被重载
public final void test(){}
public final void test(String arg){}
}
final 修饰的类不能被继承。当子类继承父类时,将可以访问到父类内部数据,并可通过重写父类方法来改变父类方法的实现细节,这可能导致一些不安全的因素。为了保证某个类不可被继承,则可以使用 final 修饰这个类。
下面代码示范了 final 修饰的类不可被继承。
final class SuperClass {
}
class SubClass extends SuperClass { //编译错误
}
因为 SuperClass 类是一个 final 类,而 SubClass 试图继承 SuperClass 类,这将会引起编译错误。
1. final 修饰类中的变量
表示该变量一旦被初始化便不可改变,这里不可改变的意思对基本类型变量来说是其值不可变,而对对象引用类型变量来说其引用不可再变。
其初始化可以在两个地方:
一是其定义处,也就是说在 final 变量定义时直接给其赋值;
二是在构造方法中。
这两个地方只能选其一,要么在定义时给值,要么在构造方法中给值,不能同时既在定义时赋值,又在构造方法中赋予另外的值。
2. final 修饰类中的方法
说明这种方法提供的功能已经满足当前要求,不需要进行扩展,并且也不允许任何从此类继承的类来重写这种方法,但是继承仍然可以继承这个方法,也就是说可以直接使用。
在声明类中,一个 final 方法只被实现一次。
3. final 修饰类
表示该类是无法被任何其他类继承的,意味着此类在一个继承树中是一个叶子类,并且此类的设计已被认为很完美而不需要进行修改或扩展。
对于 final 类中的成员,可以定义其为 final,也可以不是 final。而对于方法,由于所属类为 final 的关系,自然也就成了 final 型。也可以明确地给 final 类中的方法加上一个 final,这显然没有意义。
文章浏览阅读672次。linux 查看文件内容的命令观看档案内容 :cat, tac, more, less, head, tail, nl, 刚刚我们提到的都只是在于显示档案的外观,或者是移动与复制一个档案或目录而已,那么如果我们要视察一个档案的内容时,该如何是好呢?!这里有相当多有趣的指令可以来分享一下:最常使用的显示档案内容的指令可以说是 cat 与 more 及 less 了!此外,如果我们要查看一个很大型的档..._如何查看linux下所有.doc
文章浏览阅读3.4k次,点赞6次,收藏7次。1. Flat shading:根据表面法向量计算光照,并应用到整个面片上;速度最快,效果最差,容易暴露物体的多边形本质;2. Phong shading:注意与Phong反射模型(Phong reflection model)区分开;根据顶点的法向量插值计算出表面法向量,再逐像素计算光照;速度最慢,但效果最好;3. Gouraud shading:根据顶点_phone的光照模型比gouraud
文章浏览阅读283次。一、简析 单例模式原则就是该类自己创建自己的对象,且只能有一个对象被创建。一般情况对于打印机,数据库连接等减少内存开销,避免多线程同时访问问题会使用该模式。 根据原则: 只能有一个实例:必须私有构造函数不给其他函数创建机会,且每次调用需要判断是否已经存在实例,为了让该实例始终存在需static; 必须自己创建实例:由于构造函数私有,只能在类自身内部实例化对象,所以只能通过静态方法调用实例化函
文章浏览阅读3.1k次,点赞2次,收藏25次。常见浏览器兼容性问题与解决方案 所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。在大多数情况下,我们的需求是,无论用户用什么浏览器来查看我们的网站或者登陆我们的系统,都应该是统一的显示效果。所以浏览器的兼容性问题是前端开发人员经常会碰到和必须要解决的问题。 在学习浏览器兼容性之前,我想把前端开发人员划分为两类: 第一类是精确按照..._execcommand important
文章浏览阅读224次。非法关机导致Outlook2007无法正常启动,运行Outlook,界面显示“无法启动wicrosoft office outlook ,无法打开outlook窗口”的错误信息。0.首先备份你的邮件,文件名一般为outlook.pst。在你的c盘用户文件下你的用户下的appdata-mirosoft-outllok目录中,个别机器可能不一样,可以自己查找!1.到你..._outlook2007对话历史无法打开某个窗体区域
文章浏览阅读200次。删除链表中重复的结点相似题目:leetcode-java 删除排序链表中的重复元素–保留一个元素leetcode-java 删除排序链表中的重复元素II – 不保留重复元素上面用的方法会多一点,可以从多个角度理解一下题目描述: 在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5问题分析: 方法一: 直接修改 _js移除链表中的重复节点
文章浏览阅读826次。maven 引用的包<!--反序列化 php--> <dependency> <groupId>org.sction</groupId> <artifactId>phprpc</artifactId> <version>3.0.2</version> </dependency主要的操作方法: public static Map<String, Ob_phpserializer
文章浏览阅读3k次。目录 1.从单个表中查询所需的信息罗斯文数据库中,选择”采购订单“表,创建——查询向导——简单查询选择查询字段设置查询表名称,完成 2.从多个表中查询所需要的数据创建——查询向导——简单查询——选择数据表选择这个表字段选择第二表及字段设置查询表名称,完成在使用数据库时,有时可能希望查看表中的所有数据,但有时可能只希望查看某些字段列中的数据,或者只希望在某些字段列满足某些条件时查看数据,为此可使用选择查询。创建选择查询有两种方法:使用查询向导和在设计..._查询向导中不带选择条件的选择查询是啥
文章浏览阅读2k次。 1. 墨菲定律 “墨菲定律”源自于一位名叫墨菲的美国上尉。因为他认为某位同事是个倒霉蛋,便不经意地说了句笑话:“如果一件事情有可能被弄糟,让他去做就一定会弄糟。”后来这句话也就被延伸拓展,出现了一些其它的表达形式,比方说“ 如果坏事有可能发生,不管这种可能性多么小,它总会发生,并引起最大可能的损失”,“会出错的,终将会出错”等等。 基本上而言,根据“墨菲定律”可以推出_断言醒悟
文章浏览阅读267次。垂直外边距的塌陷首先需要明确塌陷只会发生在块级元素的相邻垂直外边距间在使用CSS的垂直外边距样式时,相邻元素和父子元素都有可能发生相邻垂直外边距的塌陷(相邻元素是上方元素的下外边距和下方元素的上外边距之间,父子元素是父元素的上外边距和子元素的上外边距之间),为了在编写静态页面时避免由于垂直外边距的塌陷导致的布局混乱,需要了解塌陷时垂直外边距的表现和产生的原因——知道原因才能更好的解决问题塌陷时外边距的计算方式在《CSS权威指南》一书中对这种塌陷发生的描述非常的生动,书中将包围元素的外边距比作透明的塑_垂直外边距的塌陷
文章浏览阅读2.2k次。单用户模式的作用在使用Linux系统中,维护人员经常会碰到一个问题,就是在拥有root账号权限和密码的用户中,总是会出现忘记root密码的情况。遇到这种情况,一般情况下,维护人员就会通过最常用的方法进行root密码重置,那就是单用户模式。其次,单用户最突出且实用的一个好处就是:可以无密码登录,所以,在忘记密码时,可以进入单用户模式修改登录密码。方法一先重启系统在Linux系统启动 内核启动顺序选择..._linux6进入单用户
文章浏览阅读297次。转自 http://blog.sina.com.cn/s/blog_4062094e01008tc0.html 一些大概有价值的网站,需要进一步的补充和甄别。 终于发现把有用的网站放到收藏夹里也不可靠了,总是丢,也疏于整理。现在在 www.g...