不可变的类比可变的类更容易设计、实现和使用。
为了使类成为不可变,要遵循下面五条规则:
1、不要提供任何会修改对象状态的方法。
2、保证类不会被扩展。
3、使所有的域都是final的。
4、使所有的域都成为私有的。
5、确保对于任何可变组件的互斥访问。
不可变对象本质上是线程安全的,他们不要求同步。
不可变对象可以自由地共享。
“不可变对象可以被自由的共享”导致的结果是,永远也不需要进行保护性拷贝。
不仅可以共享不可变对象,甚至也可以共享他们的内部信息。
不可变对象对其他对象提供了大量的构件(building blocks)。
不可变对象真正唯一的缺点是,对于每一个值都需要一个单独的对象。
让不可变对象变成final的另外一个方法就是,让类的所有构造器都变成私有的或者包级私有的,并添加共有的静态工厂(static factory)来替代共有构造器。
除非有很好的理由要让类成为可变的类,否则就应该是不可变的。
如果类不能做成不可变的,但也应该尽量限制他的可变性。
除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。
构造器应该创建完全初始化的对象,并建立起所有的约束关系。不要在构造器或者静态工厂之外再提供共有的初始化方法。
为了使类成为不可变,要遵循下面五条规则:
1、不要提供任何会修改对象状态的方法。
2、保证类不会被扩展。
3、使所有的域都是final的。
4、使所有的域都成为私有的。
5、确保对于任何可变组件的互斥访问。
不可变对象本质上是线程安全的,他们不要求同步。
不可变对象可以自由地共享。
“不可变对象可以被自由的共享”导致的结果是,永远也不需要进行保护性拷贝。
不仅可以共享不可变对象,甚至也可以共享他们的内部信息。
不可变对象对其他对象提供了大量的构件(building blocks)。
不可变对象真正唯一的缺点是,对于每一个值都需要一个单独的对象。
让不可变对象变成final的另外一个方法就是,让类的所有构造器都变成私有的或者包级私有的,并添加共有的静态工厂(static factory)来替代共有构造器。
除非有很好的理由要让类成为可变的类,否则就应该是不可变的。
如果类不能做成不可变的,但也应该尽量限制他的可变性。
除非有令人信服的理由要使域变成是非final的,否则要使每个域都是final的。
构造器应该创建完全初始化的对象,并建立起所有的约束关系。不要在构造器或者静态工厂之外再提供共有的初始化方法。
Demo:
/*
* @(#)TimerTask.java 1.11 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.util;
/**
* A task that can be scheduled for one-time or repeated execution by a Timer.
*
* @author Josh Bloch
* @version 1.11, 11/17/05
* @see Timer
* @since 1.3
*/
public abstract class TimerTask implements Runnable {
/**
* This object is used to control access to the TimerTask internals.
*/
final Object lock = new Object();
/**
* The state of this task, chosen from the constants below.
*/
int state = VIRGIN;
/**
* This task has not yet been scheduled.
*/
static final int VIRGIN = 0;
/**
* This task is scheduled for execution. If it is a non-repeating task,
* it has not yet been executed.
*/
static final int SCHEDULED = 1;
/**
* This non-repeating task has already executed (or is currently
* executing) and has not been cancelled.
*/
static final int EXECUTED = 2;
/**
* This task has been cancelled (with a call to TimerTask.cancel).
*/
static final int CANCELLED = 3;
/**
* Next execution time for this task in the format returned by
* System.currentTimeMillis, assuming this task is scheduled for execution.
* For repeating tasks, this field is updated prior to each task execution.
*/
long nextExecutionTime;
/**
* Period in milliseconds for repeating tasks. A positive value indicates
* fixed-rate execution. A negative value indicates fixed-delay execution.
* A value of 0 indicates a non-repeating task.
*/
long period = 0;
/**
* Creates a new timer task.
*/
protected TimerTask() {
}
/**
* The action to be performed by this timer task.
*/
public abstract void run();
/**
* Cancels this timer task. If the task has been scheduled for one-time
* execution and has not yet run, or has not yet been scheduled, it will
* never run. If the task has been scheduled for repeated execution, it
* will never run again. (If the task is running when this call occurs,
* the task will run to completion, but will never run again.)
*
* <p>Note that calling this method from within the <tt>run</tt> method of
* a repeating timer task absolutely guarantees that the timer task will
* not run again.
*
* <p>This method may be called repeatedly; the second and subsequent
* calls have no effect.
*
* @return true if this task is scheduled for one-time execution and has
* not yet run, or this task is scheduled for repeated execution.
* Returns false if the task was scheduled for one-time execution
* and has already run, or if the task was never scheduled, or if
* the task was already cancelled. (Loosely speaking, this method
* returns <tt>true</tt> if it prevents one or more scheduled
* executions from taking place.)
*/
public boolean cancel() {
synchronized(lock) {
boolean result = (state == SCHEDULED);
state = CANCELLED;
return result;
}
}
/**
* Returns the <i>scheduled</i> execution time of the most recent
* <i>actual</i> execution of this task. (If this method is invoked
* while task execution is in progress, the return value is the scheduled
* execution time of the ongoing task execution.)
*
* <p>This method is typically invoked from within a task's run method, to
* determine whether the current execution of the task is sufficiently
* timely to warrant performing the scheduled activity:
* <pre>
* public void run() {
* if (System.currentTimeMillis() - scheduledExecutionTime() >=
* MAX_TARDINESS)
* return; // Too late; skip this execution.
* // Perform the task
* }
* </pre>
* This method is typically <i>not</i> used in conjunction with
* <i>fixed-delay execution</i> repeating tasks, as their scheduled
* execution times are allowed to drift over time, and so are not terribly
* significant.
*
* @return the time at which the most recent execution of this task was
* scheduled to occur, in the format returned by Date.getTime().
* The return value is undefined if the task has yet to commence
* its first execution.
* @see Date#getTime()
*/
public long scheduledExecutionTime() {
synchronized(lock) {
return (period < 0 ? nextExecutionTime + period
: nextExecutionTime - period);
}
}
}