final,助你排除不稳定

      【友情提示,想看懂本篇请熟悉类的变量的分类、方法重载、重写及相关内容】

 

      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());
	}
}

 

本篇有点细点我解释的不是很清楚,如果有人懂的还好,但是不懂的请回头耐心的复习基础,程序员是要有基本的思考能力和耐心,很多时候程序员是把抽象的思路变成可行的路! 请相信,我行的...

      

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值