【友情提示,想看懂本篇请熟悉类的变量的分类、方法重载、重写及相关内容】
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());
}
}
本篇有点细点我解释的不是很清楚,如果有人懂的还好,但是不懂的请回头耐心的复习基础,程序员是要有基本的思考能力和耐心,很多时候程序员是把抽象的思路变成可行的路! 请相信,我行的...