参考:http://www.importnew.com/7553.html
final 关键字
简单来说
- final关键字不可变
- final方法不可被重写
- final类不可被继承
final变量
// 某个类声明了了一个成员为final
class xxx {
public static final String LOAN = "loan";
}
// main函数内
LOAN = new String("loan") //invalid compilation error
final使得类成员不可变
static只能用于类里
final方法
class PersonalLoan{
public final String getName(){
return "personal loan";
}
}
class CheapPersonalLoan extends PersonalLoan{
@Override
public final String getName(){
return "cheap personal loan"; //compilation error: overridden method is final
}
}
final方法不可被重写
final类
final class PersonalLoan{
}
class CheapPersonalLoan extends PersonalLoan{
// compilation error: cannot inherit from final class
}
final类不可被继承。此时final的含义是该类已经够完善了,不需要再补充或更改
不可变类(immutable class)
参考: https://www.journaldev.com/129/how-to-create-immutable-class-in-java
http://www.cnblogs.com/jaylon/p/5721571.html
特性
- 成员的值不变
- 因为值不变,只能读取不能写,所以线程安全
如何建立一个不可变类?
- 类添加final修饰符,保证类不被继承。
- 保证所有成员变量必须私有,并且加上final修饰
- 不提供改变成员变量的方法,包括setter
- 通过构造器初始化所有成员,进行深拷贝(deep copy)。
- 在getter方法中,不要直接返回对象本身,而是克隆对象,并返回对象的拷贝
关于4,如果是String等不可变类的话就可直接赋值。
关于5,如果是返回String等不可变类的对象的话,不必再拷贝,可直接返回。
因为我们的目的是让成员变量不能改,最多只能读。
以下是示例代码
package com.journaldev.java;
import java.util.HashMap;
import java.util.Iterator;
public final class FinalClassExample {
private final int id;
private final String name;
private final HashMap<String,String> testMap;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* Accessor function for mutable objects
*/
public HashMap<String, String> getTestMap() {
//return testMap;
return (HashMap<String, String>) testMap.clone();
}
/**
* Constructor performing Deep Copy
* @param i
* @param n
* @param hm
*/
public FinalClassExample(int i, String n, HashMap<String,String> hm){
System.out.println("Performing Deep Copy for Object initialization");
this.id=i;
this.name=n;
HashMap<String,String> tempMap=new HashMap<String,String>();
String key;
Iterator<String> it = hm.keySet().iterator();
while(it.hasNext()){
key=it.next();
tempMap.put(key, hm.get(key));
}
this.testMap=tempMap;
}
/**
* Constructor performing Shallow Copy
* @param i
* @param n
* @param hm
*/
/**
public FinalClassExample(int i, String n, HashMap<String,String> hm){
System.out.println("Performing Shallow Copy for Object initialization");
this.id=i;
this.name=n;
this.testMap=hm;
}
*/
/**
* To test the consequences of Shallow Copy and how to avoid it with Deep Copy for creating immutable classes
* @param args
*/
public static void main(String[] args) {
HashMap<String, String> h1 = new HashMap<String,String>();
h1.put("1", "first");
h1.put("2", "second");
String s = "original";
int i=10;
FinalClassExample ce = new FinalClassExample(i,s,h1);
//Lets see whether its copy by field or reference
System.out.println(s==ce.getName());
System.out.println(h1 == ce.getTestMap());
//print the ce values
System.out.println("ce id:"+ce.getId());
System.out.println("ce name:"+ce.getName());
System.out.println("ce testMap:"+ce.getTestMap());
//change the local variable values
i=20;
s="modified";
h1.put("3", "third");
//print the values again
System.out.println("ce id after local variable change:"+ce.getId());
System.out.println("ce name after local variable change:"+ce.getName());
System.out.println("ce testMap after local variable change:"+ce.getTestMap());
HashMap<String, String> hmTest = ce.getTestMap();
hmTest.put("4", "new");
System.out.println("ce testMap after changing variable from accessor methods:"+ce.getTestMap());
}
}
不可变类的输出结果为:
Performing Deep Copy for Object initialization
true
false
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{2=second, 1=first}
ce testMap after changing variable from accessor methods:{2=second, 1=first}
可变类的输出结果为
Performing Shallow Copy for Object initialization
true
true
ce id:10
ce name:original
ce testMap:{2=second, 1=first}
ce id after local variable change:10
ce name after local variable change:original
ce testMap after local variable change:{3=third, 2=second, 1=first}
ce testMap after changing variable from accessor methods:{3=third, 2=second, 1=first, 4=new}