The fact of getInstance()
static does not mean that Calendar
is a Singleton.
A Singleton means there will be only one instance of the class in the JVM. But getInstance()
always returns a new instance:
Calendar c1 = Calendar.getInstance();
Calendar c2 = Calendar.getInstance();
System.out.println(c1 == c2); // false
The code above prints false
, since c1
and c2
are not the same instance. Note that although getInstance()
be static, a new instance is always returned.
In this case, the method getInstance()
is working with a Static Factory method. Just because there is a static method that returns an instance does not necessarily mean that this instance will be a Singleton.
How to copy an instance
The detail is that getInstance()
returns a Calendar
which corresponds to the current date and time. That is, c1
and c2
will not have exactly the same values.
If you want to get a new instance with the same values as the original, just copy it using the method clone()
. Then you can change the clone at will, without modifying the original:
Calendar calendar = Calendar.getInstance();
// criar outro Calendar, com o mesmo valor do original
Calendar clone = (Calendar) calendar.clone();
clone.add(Calendar.MONTH, 4); // somar 4 meses
With this, the clone can be changed as needed, and the calendar
original will not have its value changed.
GregorianCalendar
There was an answer in which the questioner said that he had found a solution, using directly GregorianCalendar
. The reply was deleted, but I left this additional explanation as a complement anyway.
GregorianCalendar
is a subclass of Calendar
, and it’s okay to use it directly if you want to. The detail is that you were probably already using this class without knowing.
This is because Calendar
is an abstract class, which means that it is not possible to create instances directly with new Calendar()
. So getInstance()
actually returns some subclass of Calendar
, based on the Locale
JVM standard. And in the vast majority of cases* (for almost all locales), the return is a GregorianCalendar
:
Calendar calendar = Calendar.getInstance();
System.out.println(calendar.getClass()); // class java.util.GregorianCalendar
Of course you can use GregorianCalendar
directly if you want. But you can also continue using getInstance()
without problems, and if you want a Calendar
is not modified, create copies of it using clone()
.
* From what I saw in android documentation, GregorianCalendar
seems to be the only native subclass. However, in JDK there are other implementations, so some locales may return different subclasses.
java.time
Depending on the version of Anroid, you can also use the bundle java.time
(see here requirements to be able to use it). This new date API is much higher than Date
and Calendar
, and in my opinion, it is very worth migrating your code to use it.
An interesting detail that would help in your case is that all classes are immutable, so any operations (like adding months to a date) always return a new instance. An example with java.time.LocalDate
:
LocalDate hoje = LocalDate.now(); // data atual
// somar 4 meses (retorna uma nova instância)
LocalDate maisQuatroMeses = hoje.plusMonths(4);
plusMonths()
(and all other methods for summing/subtracting days/months/years) returns a new instance, then the variable hoje
will remain the same (there is no need to clone the instance, as we did with Calendar
).
Another detail is that in this API there are several different classes to represent dates and times, unlike the previous API, which only has Date
and Calendar
.
For example, LocalDate
represents only the date (day, month and year). There is also LocalTime
, to represent hours (only hour, minute, second and fractions of a second), LocalDateTime
for date and time, ZonedDateTime
to deal with time zones, etc. I suggest you see the oracle tutorial and this question for more details on this API.