怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏(17)

简介: 怒肝俩月,新鲜出炉史上最有趣的Java小白手册,第一版,每个 Java 初学者都应该收藏


十七、final 关键字


尽管继承可以让我们重用现有代码,但有时处于某些原因,我们确实需要对可扩展性进行限制,final 关键字可以帮助我们做到这一点。


01、final 类


如果一个类使用了 final 关键字修饰,那么它就无法被继承。如果小伙伴们细心观察的话,Java 就有不少 final 类,比如说最常见的 String 类。


public final class String

   implements java.io.Serializable, Comparable<String>, CharSequence,

              Constable, ConstantDesc {}


为什么 String 类要设计成 final 的呢?原因大致有以下三个:


为了实现字符串常量池

为了线程安全

为了 HashCode 的不可变性

更详细的原因,可以查看我之前写的一篇文章。


任何尝试从 final 类继承的行为将会引发编译错误,为了验证这一点,我们来看下面这个例子,Writer 类是 final 的。


public final class Writer {

   private String name;


   public String getName() {

       return name;

   }


   public void setName(String name) {

       this.name = name;

   }

}


尝试去继承它,编译器会提示以下错误,Writer 类是 final 的,无法继承。


image.png


不过,类是 final 的,并不意味着该类的对象是不可变的。


Writer writer = new Writer();

writer.setName("沉默王二");

System.out.println(writer.getName()); // 沉默王二


Writer 的 name 字段的默认值是 null,但可以通过 settter 方法将其更改为“沉默王二”。也就是说,如果一个类只是 final 的,那么它并不是不可变的全部条件。


如果,你想了解不可变类的全部真相,请查看我之前写的文章这次要说不明白immutable类,我就怎么地。突然发现,写系列文章真的妙啊,很多相关性的概念全部涉及到了。我真服了自己了。


把一个类设计成 final 的,有其安全方面的考虑,但不应该故意为之,因为把一个类定义成 final 的,意味着它没办法继承,假如这个类的一些方法存在一些问题的话,我们就无法通过重写的方式去修复它。



02、final 方法


被 final 修饰的方法不能被重写。如果我们在设计一个类的时候,认为某些方法不应该被重写,就应该把它设计成 final 的。


Thread 类就是一个例子,它本身不是 final 的,这意味着我们可以扩展它,但它的 isAlive() 方法是 final 的:


public class Thread implements Runnable {

   public final native boolean isAlive();

}



需要注意的是,该方法是一个本地(native)方法,用于确认线程是否处于活跃状态。而本地方法是由操作系统决定的,因此重写该方法并不容易实现。


Actor 类有一个 final 方法 show():


public class Actor {

   public final void show() {

     

   }

}



当我们想要重写该方法的话,就会出现编译错误:

image.png


如果一个类中的某些方法要被其他方法调用,则应考虑事被调用的方法称为 final 方法,否则,重写该方法会影响到调用方法的使用。


一个类是 final 的,和一个类不是 final,但它所有的方法都是 final 的,考虑一下,它们之间有什么区别?


我能想到的一点,就是前者不能被继承,也就是说方法无法被重写;后者呢,可以被继承,然后追加一些非 final 的方法。没毛病吧?看把我聪明的。



03、final 变量


被 final 修饰的变量无法重新赋值。换句话说,final 变量一旦初始化,就无法更改。之前被一个小伙伴问过,什么是 effective final,什么是 final,这一点,我在之前的文章也有阐述过,所以这里再贴一下地址:


http://www.itwanger.com/java/2020/02/14/java-final-effectively.html

1)final 修饰的基本数据类型


来声明一个 final 修饰的 int 类型的变量:


final int age = 18;


尝试将它修改为 30,结果编译器生气了:


image.png


2)final 修饰的引用类型


现在有一个普通的类 Pig,它有一个字段 name:


public class Pig {

  private String name;


   public String getName() {

       return name;

   }


   public void setName(String name) {

       this.name = name;

   }

}


在测试类中声明一个 final 修饰的 Pig 对象:


final Pig pig = new Pig();

1

如果尝试将 pig 重新赋值的话,编译器同样会生气:


image.png


但我们仍然可以去修改 Pig 的字段值:


final Pig pig = new Pig();

pig.setName("特立独行");

System.out.println(pig.getName()); // 特立独行


3)final 修饰的字段


final 修饰的字段可以分为两种,一种是 static 的,另外一种是没有 static 的,就像下面这样:


public class Pig {

  private final int age = 1;

  public static final double PRICE = 36.5;

}


非 static 的 final 字段必须有一个默认值,否则编译器将会提醒没有初始化:




static 的 final 字段也叫常量,它的名字应该为大写,可以在声明的时候初始化,也可以通过 static 代码块初始化。


final 修饰的参数

final 关键字还可以修饰参数,它意味着参数在方法体内不能被再修改:


public class ArgFinalTest {

   public void arg(final int age) {

   }


   public void arg1(final String name) {

   }

}


如果尝试去修改它的话,编译器会提示以下错误:


image.png


。。。。。。


后续还会继续更新,但有些小伙伴可能就忍不住了,这份小白手册有没有 PDF 版可以白嫖啊,那必须得有啊,直接「沉默王二」公众号后台回复「小白」就可以了,不要手软,觉得不错的,请多多分享——赠人玫瑰,手有余香哦。

相关文章
|
9月前
|
设计模式 安全 Java
面向对象编程的精髓:Java设计模式 - 原型模式(Prototype)完全参考手册
【4月更文挑战第7天】原型模式是OOP中的创建型设计模式,用于通过复制现有实例创建新实例,尤其适用于创建成本高或依赖其他对象的情况。它包括Prototype接口、ConcretePrototype实现和Client客户端角色。优点是性能优化、避免子类化和动态增加产品族。实现包括定义原型接口、实现具体原型和客户端调用克隆方法。最佳实践涉及确保克隆正确性、选择深拷贝或浅拷贝及考虑线程安全。但需注意克隆方法管理、性能开销和循环引用等问题。在Java中,实现Cloneable接口和覆盖clone方法可实现原型模式。
102 4
|
9月前
|
网络协议 Java Maven
Java自救手册
Java自救手册
104 2
|
9月前
|
算法 Java
「译文」Java 垃圾收集参考手册(四):Serial GC
「译文」Java 垃圾收集参考手册(四):Serial GC
|
9月前
|
算法 Java PHP
「译文」Java 垃圾收集参考手册(一):垃圾收集简介
「译文」Java 垃圾收集参考手册(一):垃圾收集简介
|
8月前
|
Java 开发者
【技术成长日记】Java 线程的自我修养:从新手到大师的生命周期修炼手册!
【6月更文挑战第19天】Java线程之旅,从新手到大师的进阶之路:始于创建线程的懵懂,理解就绪与运行状态的成长,克服同步难题的进阶,至洞悉生命周期的精通。通过实例,展示线程的创建、运行与同步,展现技能的不断提升与升华。
50 2
|
9月前
|
Java 开发者
效率工具RunFlow完全手册之Java开发者篇
这篇手册面向Java开发者,介绍了如何使用QLExpress执行Java代码和进行方法验证。示例包括数学计算、读取系统环境变量及格式化输出。QLExpress提供运行时执行Java代码的功能,并支持QLExpress语法的脚本文件。
56 3
效率工具RunFlow完全手册之Java开发者篇
|
8月前
|
Java 数据安全/隐私保护
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
Java基础手册二(类和对象 对象创建和使用 面向对象封装性 构造方法与参数传递 this关键字 static关键字 继承 多态 方法覆盖 final关键字 访问控制权限修饰符)
49 0
|
8月前
|
存储 Java
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
55 0
|
8月前
|
存储 自然语言处理 Java
Java IO流完全手册:字节流和字符流的常见应用场景分析!
【6月更文挑战第26天】Java IO流涵盖字节流和字符流,字节流用于二进制文件读写及网络通信,如图片和音频处理;字符流适用于文本文件操作,支持多语言编码,确保文本正确性。在处理数据时,根据内容类型选择合适的流至关重要。
113 0
|
9月前
|
算法 安全 Java
「译文」Java 垃圾收集参考手册(三):GC 算法基础篇
「译文」Java 垃圾收集参考手册(三):GC 算法基础篇