Explain how `Calendar.getInstance()` and `NumberFormat.getInstance()` illustrate Factory Method in the JDK. What do they return and why is that returned type not fixed?
answer
- `getInstance()` returns the abstract base, concrete type chosen by locale
- Calendar.getInstance → usually GregorianCalendar, but locale-dependent
- NumberFormat.getInstance → DecimalFormat configured for the locale
- Named siblings: getCurrencyInstance / getPercentInstance
- Extensible via LocaleServiceProvider SPI
basics
~20 sBoth are static getInstance() factories. They don't return a fixed class — they look at your locale/region and pick the right concrete subclass (e.g. a Gregorian calendar, or a locale-specific number format) and hand it back typed as the abstract base. You get a ready, region-appropriate object without naming the concrete class.
solid answer
~50 s`Calendar.getInstance()` and `NumberFormat.getInstance()` are static factory methods whose return type is an abstract base (`Calendar`, `NumberFormat`) but whose actual concrete class depends on the runtime context — chiefly the default or supplied `Locale`. `Calendar.getInstance()` typically returns a `GregorianCalendar`, but in a locale whose calendar system differs it can return another implementation (e.g. a Buddhist or Japanese calendar). `NumberFormat.getInstance()` returns a `DecimalFormat` configured for the locale's grouping/decimal symbols, and through a `LocaleServiceProvider` SPI a third party could supply a different concrete formatter. The point is *deferred, context-sensitive instantiation*: the caller states intent ("give me a calendar / a number formatter") and the factory selects the concrete type. This keeps locale and calendar-system logic inside the JDK rather than forcing every caller to branch on region, and lets the JDK add or change implementations without breaking code that only references the abstract type.
go deeper
Can say getInstance() gives you a ready-made object suited to your locale, typed as the abstract base, without you naming the concrete class.
Explains that the concrete subtype is chosen from the runtime locale, gives the usual concretes (GregorianCalendar, DecimalFormat), and names the sibling intent-specific factories.
Connects it to deferred/context-sensitive instantiation and extensibility via the locale-services SPI, and notes a factory may return the same class differently configured rather than different classes.
Discusses how this design isolates region/calendar policy inside the platform, the API-stability and SPI-extensibility guarantees it buys, and trade-offs such as default-locale global state and the value of passing an explicit Locale for determinism.
## Setting the scene: locale and abstraction A **Locale** is a JDK object describing a language/region/cultural setting (e.g. US English, France, Japan). Different locales format numbers differently (`1,234.5` vs `1.234,5`) and may even use different *calendar systems* (Gregorian, Buddhist, Japanese imperial). Code that hard-codes one behavior is wrong for other regions. An **abstract base class** like `java.util.Calendar` or `java.text.NumberFormat` defines *what* you can do (get a field, format a number) without committing to *how*. Concrete subclasses (e.g. `GregorianCalendar`, `DecimalFormat`) provide the how. ## How `getInstance()` is a Factory Method `Calendar.getInstance()` is a **static factory method**: a `static` method that returns an object typed as the abstract base. Internally it: 1. reads the current default `Locale` (or the one you pass to an overload), 2. determines the appropriate **calendar system** for that locale, 3. constructs and returns the matching concrete subclass, configured with the right time zone and locale. For most Western locales that concrete class is `GregorianCalendar`, but the *declared* return type is just `Calendar`, so the JDK is free to return a different subclass elsewhere. The caller writes `Calendar c = Calendar.getInstance();` and never names `GregorianCalendar`. This is **deferred instantiation** — the decision of *which class* is deferred from the caller to the factory, and made from runtime context rather than at the call site. `NumberFormat.getInstance()` works the same way: it returns a `NumberFormat`, concretely usually a `DecimalFormat`, set up with the locale's grouping separator, decimal separator, and digit symbols. Sibling factories (`getCurrencyInstance()`, `getPercentInstance()`, `getIntegerInstance()`) are *named* factory methods — each name expresses a distinct intent, which a constructor's fixed name could not. ## Why the returned type is intentionally not fixed Three reasons: - **Context sensitivity.** The correct concrete type depends on the locale, which is only known at runtime. A factory can branch on it; a constructor (fixed to one class) cannot. - **Extensibility via SPI.** A **Service Provider Interface (SPI)** is a JDK mechanism letting third parties plug in implementations. `NumberFormat` consults `NumberFormatProvider` / `LocaleServiceProvider`, so the concrete formatter for a locale can be supplied externally. Callers coded to `NumberFormat` automatically benefit. - **Evolution.** The JDK can change or optimize the concrete class between versions without breaking callers, because they only depend on the abstract return type. ## Concrete usage ```java NumberFormat fr = NumberFormat.getInstance(Locale.FRANCE); String s = fr.format(1234.5); // "1 234,5" — French grouping & decimal NumberFormat us = NumberFormat.getCurrencyInstance(Locale.US); String p = us.format(9.5); // "$9.50" Calendar cal = Calendar.getInstance(); // concrete subtype chosen from default locale ``` Note `fr` and `us` are almost certainly both `DecimalFormat` instances under the hood — but configured differently — illustrating that a factory can return the *same* concrete class in *different configurations*, not only different classes. Either way the caller is shielded. ## The takeaway for interviews These methods show Factory Method's intent in the JDK: *the caller expresses what it needs; the factory uses runtime context (locale/region) to pick and configure the concrete object, returning it as an abstraction.* Mentioning the SPI extensibility and the named-sibling factories (`getCurrencyInstance`, etc.) signals depth beyond the textbook definition.
- Why does `NumberFormat` offer `getCurrencyInstance()` and `getPercentInstance()` as separate methods instead of one constructor with a flag?Distinct, self-documenting names express distinct intents and read more clearly than a boolean/enum flag. Constructors can't have different names, so multiple intents with the same parameter list could not be expressed as overloaded constructors at all.
- How can a third party change what concrete type these factories return?Through the locale-services SPI (e.g. `NumberFormatProvider` / `LocaleServiceProvider`): a provider registered on the module/classpath can supply a locale-specific implementation the factory will return, without callers changing.
saying these in an interview costs you the question
- Insisting `Calendar.getInstance()` always returns a `GregorianCalendar` — it depends on the locale's calendar system.
- Saying the caller must downcast to `GregorianCalendar` to use it — you should program to the `Calendar` API.
- Believing different locales mean different concrete classes for NumberFormat — usually it's the same `DecimalFormat` class with different configuration.
- Confusing these with Abstract Factory — there's no factory object you hold; these are static factory methods.