1. final变量:final修饰的变量一旦获得了初始值之后就不可被改变。final可以修饰成员变量,局部变量,形参。
1.1 final成员变量:final修饰的类属性(static)可以在静态初始化块或声明时指定初始值;final修饰的实例属性可以在非静态初始化块,构造器或声明时指定初始值。
- class TestFinal {
- final int a = 1; //声明时指定初始值
- final int b;
- final int c;
- static final String NAME_1 = "MengLei"; //声明时指定初始值
- static final String NAME_2;
-
- {
- b = 2; //使用非静态初始化块为实例属性b指定初始值
- }
- TestFinal() {
- c = 3; //使用构造器为实例属性c指定初始值
- }
- static {
- NAME_2 = "MengChen"; //使用静态初始化块为类属性指定初始值
- }
- }
1.2 final修饰局部变量:如果final休斯的局部变量在声明时没有指定初始值,则可以在后面代码中指定,但只能一次。
- public class Temp {
- public static void main(String[] args) {
- final int a = 1; //声明时指定初始值
- final int b;
- b = 2; //后来指定初始值
- b = 3; //报错:不能重复指定
- }
- public void test(final int a) {
- a = 3; //报错:不能对final形参赋值
- }
- }
1.3 final修饰基本类型变量和引用类型变量的区别:当final修饰基本类型变量时,不能对基本类型变量重新赋值,因此变量值不能被改变;但对于引用变量而言,它保存的仅仅是一个引用,final只保证这个引用不能指向别的地址空间,但是被引用的对象的内容是可以改变的。
2. final方法:final修饰的方法不能被重写。但是可以重载。
3. final类:final修饰的类不可以有子类。
4. 不可变类:创建类的实例后,实例的属性是不可改变的。Java提供的包装类和String类都是不可变类。
- Double d = new Double(1.1);
- String s = new String("ML");
上面这两个类通过传入的参数实例化各自的对象,但是他们的属性是不可改变的。
如果需要创建自定义的不可变类,需要:
a. 使用private和final修饰成员属性。
b. 提供带参数的构造器,并通过传入的参数初始化成员属性。
c. 仅为类属性提供getter方法,不要提供setter方法。
d. 最好重写Object类的hashCode和equals方法。equals方法根据关键属性作为判断相等的标准,此外还需要保证两个用equals方法判断相等的对象的hashCode也相等。
5. 缓存不可变类实例:不可变类的实例不可改变,可以很方便的被多个对象共享。如果程序经常需要使用相同的不可变类实例,则应该考虑缓存这种不可变类的实例。毕竟多次重复创建相同对象没有太大意义,而且加大了系统开销。
- public class Temp {
- public static void main(String[] args) {
- CacheImmutale ci1 = CacheImmutale.valueOf("MengLei");
- CacheImmutale ci2 = CacheImmutale.valueOf("MengLei");
- System.out.println(ci1==ci2);
- }
- }
-
- class CacheImmutale {
- private final String name;
- private static CacheImmutale [] cache = new CacheImmutale [10];
- private static int pos = 0;
-
- public CacheImmutale(String name) {
- this.name = name;
- }
- public String getName() {
- return this.name;
- }
- public static CacheImmutale valueOf(String value) {
- for (int i=0;i<pos;i++) {
- if (cache[i] != null && cache[i].getName().equals(value)) {
- return cache[i];
- }
- }
- if (pos == 10) {
- pos = 0;
- cache[pos++] = new CacheImmutale(value);
- return cache[pos-1];
- }
- else {
- cache[pos++] = new CacheImmutale(value);
- return cache[pos-1];
- }
- }
- public boolean equals(Object obj) {
- if (obj instanceof CacheImmutale) {
- CacheImmutale ci = (CacheImmutale)obj;
- if (ci.getName().equals(this.getName()))
- return true;
- else
- return false;
- }
- else
- return false;
- }
- public int hashCode() {
- return this.getName().hashCode();
- }
- }
java提供的Integer类就采用了这种处理策略,如果用new构造器来创建Integer对象,则每次返回全新的Integer对象;如果用valueOf方法创建Integer对象,则会缓存该方法的创建。