Calender不是单例
程序员文章站
2022-07-12 18:48:08
...
在我们使用Calender的时候,使用过Calendar.getInstance()来获取一个日期类的对象,这种方式跟单例的获取方式一样,那么它到底是不是单例呢,如果是单例的话,一个对象修改内容之后,另外一个线程中的数据不久乱套了吗?从试验以及源码中可以得出,Calendar不是单例。
测试:
Calendar c1 = Calendar.getInstance(); Calendar c2 = Calendar.getInstance(); //输出true System.out.println("c1.equals(c2) is : "+c1.equals(c2)); //输出false System.out.println("c1 == c2 is : "+ (c1 == c2));
可以看出,两个实例的值相等,但是引用却不相等。
下面看看jdk的源码中的写法:
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); }
可以看出,根据不同的语言环境,创建了不同的日期对象实例,低版本的JDK中,只对泰语做了特殊处于,高版本中又增加了日本的,具体实现有何不同,可以去看一下具体不同日期类的实现。
而至于Calendar为什么用Calendar.getInstance()来获取实例对象,是因为它本身是个抽象类,是各种日期类实现类的父类,提供了Calendar.getInstance()给我们方便调用,根据不同的语言环境采取不同的实现,JDK帮我们封装了这些细节,所以直接使用
GregorianCalendar c1 = new GregorianCalendar();
来创建日期类的实例,其实也是可以的,但无疑破坏了封装性,多态性,我们也得像getInstance()方法里面处理的一样,根据不同的语言环境做不同的处理,所以我们还是不要破坏的好。