【友情提示,想看懂本篇请熟悉类的变量的分类、方法重载、重写及相关内容】
final关键字,正如它的英文释义-- 不可更改的,所以被它修饰的属性或者方法一旦确定下来,就不能更改了。鉴于它的整个特性,所以常常我们以之定义常量属性、定义不可被重写的父类方法、不可改变的类。
我们知道,Java中的变量可以分为成员变量和局部变量(不清楚分类的可点击:Java起航 -- 类的变量 ),方法就没有比较本质的区别(方法作为形参暂不考虑,有机会后面会提到);我们也知道Java中是不能使用未初始化的变量。也许有童鞋会疑问,当我们在方法中使用未初始化的变量怎么就不报错?如
class A{
private int salary; //未初始化怎么可以正常编译及使用
public int getSalary(){
return salary;
}
}
这时,我们就要抛出一个“定理”就能解释了:Java的编译器只会对非final修饰的成员变量执行默认初始化,赋予默认值,而不会对final成员变量执行默认初始化,至于局部变量,至始至终就不会进行默认的初始化(不得不说它是个可怜的娃...),所以你现在就能明白上面的程序是怎么回事,打印方法结果会得到一个0,至于结论,自己总结!
为了使被final修饰的变量可以正常使用,但又不能依靠编译器默认初始化,所以只能自己动手让它显式初始化。以下是各种变量初始化的时机:
final修饰的类属性的初始化方式有:要么声明时直接赋值,要么在静态初始块中初始化;
final修饰的对象属性的初始化方式有:要么声明时直接赋值,要么非静态初始块或者构造器中;
final修饰的方法内部的局部变量: 直接或者间接声明时初始化。
final修饰的方法形参的局部变量: 初始化过程参考形参初始化(页面底部)中的方法传递,但注意不能再在方法内对形参赋值
final修饰的代码块的局部变量: 与方法内部的局部变量一致。
如果你对上面存有疑惑,那么你再记住这一句话:一旦被初始化就不能再被赋值。关于上面的言论,个人就不贴出代码了,如果有“基础”的你,我相信你绝对可以翻译成测试程序的。
如果final修饰了基本类型的变量,那么这个变量与局部变量如同一撤,但是final修饰了对象的引用变量,就可以修改改变量的值,如
class B{
private int age;
public B( int a ){
age = a;
}
public int getAge( ){
return this.age;
};
public void setAge( int temp){
this.age = temp;
}
public static void main(String[] args){
// use final to declare the B object
final B b = new B(15);
System.out.println(b.getAge()); // print 15
b.setAge(20);
System.out.println(b.getAge()); // print 20
}
}
至于final修饰的方法,只能被重载,而不能被重写。我们可以这么理解这句话:被重载的方法通过形参列表的不同可以标识出每个方法的唯一性,但是重写,只是对方法的执行体进行修改,并没有对方法的唯一标识进行修改(方法的唯一标识可以从调用方法的过程总结:调用方法的过程(页面底部);但是我们又从final关键字得到浓浓的唯一味道,所以我们很能理解方法可以被重载但不能被重写。
被final修饰的类不能有子类,至于缘由,个人可仿照方法进行推演找出总结的答案。下面着重介绍不可变类。
不可变类(immutable class),是指创建的实例不能重新对实例的属性进行重定义,比如String
// create String object
String peo = new String("people");
// peo.setValue("hello"); won't work.
如果要创建自定义的不可变类,可遵守如下规则:
1、类中定义的属性建议被private修饰、但必须被final修饰。private是封装性,final是不可变性
2、对属性可以提供getter方法,但不能定义setter方法,即使定义了也会报编译错误。
3、必须具有完整的有参构造,其作用是根据传入的参数对属性执行初始化
4、有选择的重写Object类的hashCode和equals方法。
相关代码:
package com.Immutable;
/**************************************************
* simply define a immutable class. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-12 下午04:26:15
***************************************************/
// immutable class extends Object class defaultly.
public class ImmutableTest1 {
// declare variables
private final String name;
private final int age;
// construtor with fields
private ImmutableTest1(String name, int age) {
this.name = name;
this.age = age;
}
// getters
public String getName() {
return name;
}
public int getAge() {
return age;
}
// override equals and hashCode from Object
@Override
public boolean equals(Object obj){
if( obj instanceof ImmutableTest1){
if(this.getName().equals(((ImmutableTest1) obj).getName())){
System.out.println(1);
return true;
}
System.out.println(2);
return false;
}
System.out.println(3);
return false;
}
@Override
public int hashCode() {
return name.hashCode();
}
public static void main(String[] args){
ImmutableTest1 it1 = new ImmutableTest1("张三", 19);
ImmutableTest1 it2 = new ImmutableTest1("张三", 19);
System.out.println(it1.equals(it2));
System.out.println(it1.name.hashCode());
System.out.println(it2.name.hashCode());
}
}
运行结果:
1
true
774889
774889
分 析 :看代码注释
上面的结论告诉了我们按上述要求定义的类是不可变类。假如不可变类中的final属性是组成了一个普通的类,情况又会怎样呢?且看如下代码
相关代码:
/**************************************************
* make up a immutable class with a common class. 【 群:152380972 】
* @author: 瘋叻ハ.兩
* @revision: 1.0
* @create-time: 2011-9-12 下午04:47:06
***************************************************/
public class ImmutableTest2 {
public static void main(String[] args) {
Name n = new Name("悟空","孙");
Person p = new Person(n);
System.out.println("改前是:" + p.getName().getFirstName());
// reset firstName
n.setFirstName("八戒");
System.out.println("改后是:" + p.getName().getFirstName());
}
}
// immutable class
class Person{
final Name name;
public Person(Name n){
this.name = n;
}
public Name getName(){
return this.name;
}
}
// simple class
class Name{
private String firstName;
private String lastName;
public Name(String fir, String las){
this.firstName = fir;
this.lastName = las;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
运行结果:
改前是:悟空
改后是:八戒
分 析 :把组成的类看成是一个引用变量则结果就一目了然了
从上述结果我们看到了Person类被破坏了。为了保护Person类的属性的不可变,我们只需将Person类改动如下代码:
// immutable class
class Person{
final Name name;
public Person(Name n){
this.name = new Name(n.getFirstName(), n.getLastName());
}
public Name getName(){
return new Name(name.getFirstName(), name.getLastName());
}
}
本篇有点细点我解释的不是很清楚,如果有人懂的还好,但是不懂的请回头耐心的复习基础,程序员是要有基本的思考能力和耐心,很多时候程序员是把抽象的思路变成可行的路! 请相信,我行的...
分享到:
相关推荐
这次发布的1.9.2 Nexus Final是该软件的一个重要里程碑,意味着在之前的版本基础上进行了改进和优化,为用户提供更稳定、功能更全面的论坛环境。 描述中的链接“http://forums.xmbforum.com/”可能是XMB论坛的官方...
路由器不会从所有接口转发数据包,只会通过最适合的接口转发,排除接收数据包的接口。 2. 递归查找:路由器在处理数据包前往10.0.0.0/8和192.168.1.0/24网络时,需要进行递归查找,因为这些网络不是直接连接的,...
当用户遇到技术问题时,这部分内容将提供必要的信息来帮助用户解决常见的问题,从而确保AgentView的稳定运行。 ### 6. 参考资料 最后一部分介绍了TSAPI相关参考资料,为开发者提供了学习和深入了解TSAPI SDK的资源...
标题 "java-parser-api-1.1.3.Final.zip" 提供的信息暗示这可能是一个Java解析API的版本,特别地,版本号为1.1.3.Final。这个API很可能用于解析和操作JSON(JavaScript Object Notation)数据,这是一种轻量级的数据...
- 类加载器遵循双亲委派模型,这有助于避免类的重复加载,并确保了系统的稳定性。 8. **"main"是否为Java中的关键字:** - 在Java中,“main”不是关键字。它是用于标识程序入口点的方法名称。 - 但是,main方法...
6、透明皮肤排除设备管理器、任务管理器、注册表编辑器 7、部署分辨率默认修改为“1024 x 768” 8、修正SRS部分VIAIDE残留问题 9、调整用于Windows Server 2003的Sysprep程序组,避免出现部署后非系统分区不自动分配...
WinPE是一种小型操作系统,主要用于故障排除、修复计算机以及安装Windows操作系统。由于WinPE本身的功能有限,因此能够有效地在其中添加所需的程序快捷方式对于提升工作效率具有重要意义。 #### 方法详解 为了实现...
即使程序抛出了异常并被捕获,finally块中的代码也会执行,这有助于资源的正确释放和程序的稳定性。 - **finalize**:与垃圾回收机制相关联,是Object类中的一个方法,可以在对象被垃圾回收前执行特定的清理操作。...
《理光2553/3053/3353维修手册》是一份针对理光MP2553SP、MP3053SP、MP3053SP、MP3353SP以及MP3353SP系列打印机的中文维修指南,为用户提供详尽的设备维护和故障排除方案。这份手册的重要性在于,它能够帮助拥有或...
例如,切换频谱不稳定的问题,可以通过调整增幅器的定时、幅度表和RC滤波器值来改善。而不良的调制频谱问题,则需要更动电源电容滤波器的值并注意电源布局。这些经验对于解决实际开发中遇到的问题非常关键。 除此...
- **final**:关键字用于声明不可变变量、方法或类。当一个变量被声明为 final 时,其值一旦初始化就不能更改;当一个方法被声明为 final 时,它不能在子类中被重写;而一个类如果被声明为 final,则该类不能被继承...
这款软件的名字可能源于知名的日本游戏系列"Final Fantasy",但在此情境下,它是与游戏无关的实用技术解决方案。 在提供的文件列表中,我们可以看到以下几个关键组件: 1. **QQWry.Dat**:这是一个包含IP地址和...
在探讨“Windows Server 2003 Sp2 下无法安装SQL Server 2008 Management Studio Express问题”这一主题时,我们首先需要理解几个关键概念和技术背景,这将有助于我们深入分析并解决所遇到的问题。 ### 技术背景 1...
Windows 2000支持FAT16和FAT32文件系统,Convert命令用于转换文件系统,Ghost是数据备份与还原软件,FinalData则用于数据恢复。"Write protect error drive A"意味着软盘被写保护,常见的光驱接口有IDE和USB,而DVD...
- 抽象方法也不能是`final`,因为`final`方法不允许被覆盖。 **4. 抽象类和接口的区别** - **抽象类**可以包含具体实现,也可以是抽象方法。 - **接口**只包含抽象方法,并且一个类可以实现多个接口。 **5. 重载...
11. **排除项** (Exclusions): 提供了不包括在性能测试中的部分,可能是因为技术限制、资源不足或其他原因。 12. **测试交付物** (Test Deliverables): 明确了测试完成后需要提供的文档、数据和报告,例如测试报告...
1. **计算机组装**:包括正确安装和拆卸计算机配件,如CPU、内存、硬盘、显卡、电源等,确保各部件之间的连接稳定且符合规范。 2. **CMOS设置**:CMOS是计算机启动时读取基本硬件信息的地方,设置第一顺序光盘启动...
例如,如果不需要Struts2 Spring插件中的Spring Beans,则可以在该依赖中添加`<exclusions>`标签来排除Spring Beans。 - **版本锁定原则**:通过在POM文件中定义版本变量,并使用`<dependencyManagement>`标签来统一...
Hyper-V采用了微内核架构设计,旨在确保系统的稳定性和性能表现。该架构的主要特点包括: 1. **Hypervisor层**:Hyper-V的核心组件运行在一个特权级别高于操作系统的环境中,被称为ring -1。这一级别的特权比传统...