单例模式应该满足每个该类的对象都指向同一块内存区域吧,Calendar显然满足。
但在这里(http://raychase.iteye.com/blog/1471015)看到说“这种形式可以看做是单例的一个变体。”,变体怎么理解?
package test; import java.util.Calendar; public class LeakTest { /** * @param args */ public static void main(String[] args) { Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); Runtime run1 = Runtime.getRuntime(); Runtime run2 = Runtime.getRuntime(); System.out.println("c1.equals(c2) is " + c1.equals(c2)); System.out.println("c1 == c2 is " + (c1 == c2)); System.out.println("run1.equals(run2) is " + run1.equals(run2)); System.out.println("run1 == run2 is " + (run1 == run2)); } }
单例模式表示返回的永远是同一个对象,即对象的引用是相同的。
c1 == c2 is false
说明Calendar 不是单例模式。从实际情况分析也应该不是单例,如果c1、c2是同一个对象,那么你修改c1时会影响到c2,时间就没办法比较了。
Runtime 是单例模式。
可以参看下openjdk的源码:
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { //..... public static Calendar getInstance() { Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault()); cal.sharedZone = true; return cal; } //......... private static Calendar createCalendar(TimeZone zone, Locale aLocale) { // If the specified locale is a Thai locale, returns a BuddhistCalendar // instance. if ("th".equals(aLocale.getLanguage()) && ("TH".equals(aLocale.getCountry()))) { return new sun.util.BuddhistCalendar(zone, aLocale); } else if ("JP".equals(aLocale.getVariant()) && "JP".equals(aLocale.getCountry()) && "ja".equals(aLocale.getLanguage())) { return new JapaneseImperialCalendar(zone, aLocale); } // else create the default calendar return new GregorianCalendar(zone, aLocale); }
public class Runtime { private static Runtime currentRuntime = new Runtime(); public static Runtime getRuntime() { return currentRuntime; } /** Don't let anyone else instantiate this class */ private Runtime() {} //..... }
和我犯的一样的错,告诉你它不是单例。因为getInstance()方法得到的对象要求是不同的对象。比如今天5点,明天3点。