Localization practice questions

From OCP Java SE 25 (1Z0-831) · 14 questions on this topic

Localization practice questions from OCP Java SE 25 (1Z0-831). This pack has 14 questions tagged Localization, drawn from its timed mock exams. 8 of them are worked through in full below — the question, every option, why each is right or wrong, and the explanation.

Worked examples for Localization

  1. Question 1

    What does this print? ```java import java.util.*; public class Main { public static void main(String[] args) { Locale loc = Locale.forLanguageTag("en-GB"); System.out.print(loc.getLanguage() + "-" + loc.getCountry()); } } ```

    1. A. en-gb

      Assumes the country code is lowercased. getCountry() returns the region code in uppercase (GB); only getLanguage() is lowercase, so a fully lowercased 'en-gb' is wrong.

    2. B. GB-en

      Swaps the two subtags. The code prints getLanguage() first and getCountry() second, so the language precedes the country, not the reverse.

    3. C. en-GBCorrect answer

      forLanguageTag parses the BCP 47 tag into language subtag 'en' and region subtag 'GB'; getLanguage() returns the language in lowercase and getCountry() returns the region in uppercase, giving en-GB. (Javadoc 25 — Locale.forLanguageTag / getLanguage / getCountry)

    4. D. English-United Kingdom

      'English' and 'United Kingdom' are the human-readable names returned by getDisplayLanguage()/getDisplayCountry(), not the codes returned by getLanguage()/getCountry().

    Explanation

    forLanguageTag parses a BCP 47 tag into a language subtag and a region subtag. The plain getLanguage() and getCountry() accessors return codes rather than display names, and their case is fixed by convention no matter how the tag was typed: the language is always lowercase and the country always uppercase. Printing them in the order the getters are called yields the language code followed by the country code.

  2. Question 2

    What does this print? ```java import java.text.*; import java.util.*; public class Main { public static void main(String[] args) { System.out.print(NumberFormat.getPercentInstance(Locale.US).format(0.08)); } } ```

    1. A. 0.08%

      Skips the multiply-by-100 step that defines a percent format. The fraction 0.08 is scaled to 8 before the percent sign is appended, so it is not shown as 0.08%.

    2. B. 8%Correct answer

      A percent instance multiplies the input by 100 (0.08 becomes 8) and defaults to zero fraction digits, then appends the percent sign, giving 8%. (Javadoc 25 — NumberFormat.getPercentInstance)

    3. C. 8.00%

      8.00% would require calling setMinimumFractionDigits(2); the default fraction-digit count for a percent instance is zero.

    4. D. 0%

      0% would result only if 8 rounded to nothing; 8 is a whole number and is shown in full.

    Explanation

    A percent-format instance does two things by default: it multiplies the value by 100 and shows zero fraction digits before appending the percent sign. So a fractional input is scaled up to its whole-percentage form with no decimals. The multiply is reversed on parsing, so parsing '8%' returns 0.08.

  3. Question 3

    What does this print? ```java import java.util.*; public class Main { public static void main(String[] args) { Locale loc = Locale.forLanguageTag("de_DE"); System.out.print("[" + loc.getLanguage() + "][" + loc.getCountry() + "]"); } } ```

    1. A. [de][DE]

      Assumes the underscore is accepted like a hyphen; forLanguageTag only understands hyphens, so 'de_DE' is not parsed into subtags.

    2. B. [][]Correct answer

      BCP 47 tags separate subtags with hyphens, so 'de_DE' is a single ill-formed subtag; forLanguageTag silently discards ill-formed input rather than throwing, leaving both language and country empty, so the output is [][]. (Javadoc 25 — Locale.forLanguageTag, ill-formed subtags ignored)

    3. C. [de_DE][]

      Assumes the whole token becomes the language; an underscore is not a valid language-subtag character, so nothing is captured.

    4. D. Throws IllformedLocaleException

      forLanguageTag never throws on malformed input; IllformedLocaleException is thrown by Locale.Builder, not by forLanguageTag.

    Explanation

    forLanguageTag expects hyphen-separated BCP 47 subtags (de-DE) and silently swallows ill-formed input instead of throwing. An underscore is not a valid subtag separator, so an underscore-joined locale name parses to nothing and both accessors return empty strings. Underscores belong to bundle file names such as messages_de_DE.properties, not to language tags; exceptions on malformed locales come from Locale.Builder instead.

  4. Question 4

    A project ships three files on the classpath: `Msg.properties`, `Msg_fr.properties`, and `Msg_fr_CA.properties`. There is no `Msg_it.properties` and no `Msg_fr_FR.properties`. Which two statements about how these bundles and their locales behave are correct? (Choose two.)

    1. A. `PropertyResourceBundle` reads `.properties` files as UTF-8, so an accented value such as `café` can be written literally instead of as a `\u00e9` escapeCorrect answer

      Correct: since Java 9 PropertyResourceBundle decodes .properties files as UTF-8 (falling back to ISO-8859-1 only on malformed bytes), so an accented value like café can be written literally instead of as a \u00e9 escape.

    2. B. `ResourceBundle.getBundle("Msg", Locale.FRANCE)` throws `MissingResourceException`, because `Msg_fr_FR.properties` does not exist

      Incorrect: lookup does not need an exact language+country hit — the candidate chain for fr-FR is Msg_fr_FR, then Msg_fr, then the base, so Msg_fr answers and no MissingResourceException is thrown.

    3. C. If no bundle matches the requested locale, `getBundle` next tries the candidate bundles of the JVM's default locale, and only falls back to `Msg.properties` after thatCorrect answer

      Correct: if no candidate for the requested locale resolves, the default Control repeats the whole search for Locale.getDefault() before finally trying the base bundle, so a default-locale bundle can win.

    4. D. `Locale.of("xx", "YY")` throws `IllformedLocaleException`, because `xx` is not a registered ISO 639 language code

      Incorrect: Locale.of performs no validation and happily produces the tag xx-YY; it is Locale.Builder that validates subtag syntax and throws IllformedLocaleException (for a malformed subtag, not an unassigned one).

    Explanation

    Why `If no bundle matches the requested locale, `getBundle` next tries...` is correct: the default `ResourceBundle.Control` builds a candidate list for the *requested* locale, and if none of those resolve it repeats the whole search for `Locale.getDefault()` before finally trying the base bundle. Asking for `it-IT` on a JVM whose default locale is `fr-FR` therefore returns `Msg_fr` — the returned bundle's `getLocale()` is `fr`, not the root. This is the single most surprising thing about bundle lookup: a locale you never asked for can win. Why `PropertyResourceBundle` reads `.properties` files as UTF-8...` is correct: since Java 9 the properties reader decodes UTF-8 and only falls back to ISO-8859-1 when it meets a malformed byte sequence. Writing `greet=Bonjour café` as raw UTF-8 bytes yields the single char U+00E9; under the old ISO-8859-1 rule those two bytes would have decoded as two mojibake chars. Why the others are wrong: ``ResourceBundle.getBundle("Msg", Locale.FRANCE)` throws `MissingResourceException`...` encodes the belief that lookup needs an exact language+country hit. It does not: the candidate chain for `fr-FR` is `Msg_fr_FR`, then `Msg_fr`, then the base — so `Msg_fr` answers, and no exception is thrown. `MissingResourceException` is for when *no* bundle at all resolves, or when a key is absent from the whole parent chain. ``Locale.of("xx", "YY")` throws `IllformedLocaleException`...` confuses the two construction paths. `Locale.of` performs no validation whatsoever — it happily produces the tag `xx-YY`. It is `Locale.Builder` that validates syntax and throws `IllformedLocaleException` (for a *malformed* subtag such as `qq1`, not merely an unassigned one). Exam tip: two separate facts hide here. Bundle lookup consults the default locale *between* the requested locale and the base bundle — which is exactly why a bundle test that passes on your laptop can fail on a build server. And validation lives in `Locale.Builder`, never in `Locale.of`.

  5. Question 5

    What does this print? ```java import java.time.*; import java.time.format.*; import java.util.*; public class Main { public static void main(String[] args) { DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).withLocale(Locale.UK); System.out.print(LocalDate.of(2026, 3, 14).format(f)); } } ```

    1. A. 14 March 2026

      This is FormatStyle.LONG under Locale.UK — correct British day-first ordering, but LONG omits the weekday; FULL adds the day name on top of LONG.

    2. B. Saturday, March 14, 2026

      This is the same FULL style rendered under Locale.US — it keeps the weekday but flips to month-day order and adds a comma before the year; assuming English is English is the trap.

    3. C. 14/03/2026

      This is FormatStyle.SHORT under Locale.UK — all numeric; it is still day-first, so spotting the British ordering but guessing the wrong style lands here.

    4. D. Saturday, 14 March 2026Correct answer

      FormatStyle.FULL is the only style that spells out the day of the week (2026-03-14 is a Saturday) and Locale.UK puts the day before the month with no comma before the year, together giving Saturday, 14 March 2026.

    Explanation

    Trace: two independent choices decide this output. `FormatStyle.FULL` is the only style that spells out the day of the week, and 2026-03-14 is a Saturday. `Locale.UK` then decides the *order*: British English puts the day before the month and uses no comma between month and year. Together they give `Saturday, 14 March 2026`. Why the others are wrong: `Saturday, March 14, 2026` is the same FULL style rendered under `Locale.US` — it keeps the weekday but flips to month-day order and adds the comma before the year. This is the trap for anyone who assumes English is English. `14 March 2026` is `FormatStyle.LONG` under `Locale.UK`: correct British ordering, but LONG omits the weekday. Confusing LONG with FULL is the classic style-ladder slip; FULL adds the day name on top of LONG. `14/03/2026` is `FormatStyle.SHORT` under `Locale.UK` — all numeric. Note it is still day-first, so a student who spots the British ordering but guesses the wrong style still lands here. Exam tip: `ofLocalizedDate` needs both halves of the answer — the style picks *how much* (FULL adds the weekday, LONG spells the month, MEDIUM abbreviates it, SHORT goes numeric) and the locale picks the *order*. Also note `withLocale` returns a NEW formatter rather than mutating the receiver; a stem that calls `f.withLocale(...)` and throws the result away is testing immutability instead, and would silently fall back to the default locale.

  6. Question 6

    What does this print? ```java import java.text.*; import java.util.*; public class Main { public static void main(String[] args) { NumberFormat nf = NumberFormat.getIntegerInstance(Locale.US); System.out.print(nf.format(2.5) + " " + nf.format(3.5)); } } ```

    1. A. 2 3

      Assumes getIntegerInstance truncates (chops the fractional part) the way a cast to int does; NumberFormat rounds instead.

    2. B. 2 4Correct answer

      Correct: getIntegerInstance rounds with the default HALF_EVEN, which breaks a .5 tie toward the even neighbour, so 2.5 goes to 2 and 3.5 goes to 4.

    3. C. 2.5 3.5

      Assumes getIntegerInstance merely groups digits and leaves the fraction alone; the name is literal — it formats integers and rounds the fractional digits away.

    4. D. 3 4

      Applies HALF_UP, the everyday rule that pushes every exact tie away from zero; NumberFormat's default is HALF_EVEN, which is wrong for half of all ties (here 2.5 rounds to 2, not 3).

    Explanation

    Trace: `getIntegerInstance` returns a format with `maximumFractionDigits` of 0, so both values must be rounded to a whole number — and the rounding mode `NumberFormat` uses by default is `RoundingMode.HALF_EVEN`, not the half-up rule taught in school. HALF_EVEN breaks an exact .5 tie toward the *even* neighbour: 2.5 sits between 2 and 3, and 2 is even, so it rounds down to `2`; 3.5 sits between 3 and 4, and 4 is even, so it rounds up to `4`. The result is `2 4`. The same rule gives 0.5 -> 0, 1.5 -> 2, 4.5 -> 4 — the ties alternate rather than always climbing. Why the others are wrong: `3 4` applies HALF_UP, the everyday rounding rule, pushing every exact tie away from zero. That is the single most common wrong answer here, and it is wrong for exactly half of all ties. `2 3` assumes the integer instance truncates (chops the fractional part) rather than rounds. Truncation is what a cast to `int` does; `NumberFormat` rounds. `2.5 3.5` assumes `getIntegerInstance` merely groups digits and leaves the fraction alone. The name is literal: it formats integers, so it drops the fractional digits by rounding them away. Exam tip: `NumberFormat`'s default rounding is HALF_EVEN (banker's rounding), chosen because it does not bias a long run of sums upward. Watch for an exact `.5` tie in the stem — that is the tell that the question is testing this, and reading the tie as HALF_UP is the trap. Call `nf.setRoundingMode(RoundingMode.HALF_UP)` when you actually want the school rule.

  7. Question 7

    What does this print? ```java import java.time.*; import java.time.format.*; import java.util.*; public class Main { public static void main(String[] args) { DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).withLocale(Locale.US); System.out.print(LocalDate.of(2026, 3, 14).format(f)); } } ```

    1. A. 2026-03-14

      2026-03-14 is the ISO_LOCAL_DATE layout, not a localized style; ofLocalizedDate never emits ISO format.

    2. B. March 14, 2026

      Spelling the month in full is the LONG style, not MEDIUM.

    3. C. 3/14/26

      The numeric slash form with a two-digit year is the US SHORT style, not MEDIUM.

    4. D. Mar 14, 2026Correct answer

      ofLocalizedDate(FormatStyle.MEDIUM) pinned to Locale.US abbreviates the month to three letters and shows the full year, producing Mar 14, 2026. (Javadoc 25 — DateTimeFormatter.ofLocalizedDate / FormatStyle)

    Explanation

    ofLocalizedDate builds a locale-sensitive formatter, and pinning the locale with withLocale makes its output deterministic instead of depending on the JVM default locale. Each FormatStyle has a distinct US shape: SHORT uses numeric slashes with a two-digit year, MEDIUM abbreviates the month with a full year, and LONG spells the month out, so the MEDIUM style produces the abbreviated-month form.

  8. Question 8

    What does this print? ```java import java.text.*; import java.util.*; public class Main { public static void main(String[] args) throws Exception { NumberFormat nf = NumberFormat.getCurrencyInstance(Locale.US); Number n = nf.parse("$1,234.50"); System.out.print(n.doubleValue()); } } ```

    1. A. 1234.5Correct answer

      A currency instance can parse as well as format: it recognizes the US currency symbol, strips the grouping commas, and reads the decimal point to produce 1234.5, and printing that double drops the insignificant trailing zero. (Javadoc 25 — NumberFormat.parse / getCurrencyInstance)

    2. B. 1234.50

      1234.50 is how the value would be formatted for display; parsing yields a numeric double, and the double 1234.50 prints as 1234.5 because doubles keep no trailing zeros.

    3. C. 123450.0

      123450.0 treats the comma and dot as ignored digits; parse interprets the comma as a grouping separator and the dot as the decimal point, not as literal digits.

    4. D. Throws ParseException

      A ParseException is thrown only when the string does not match the format; the '$' symbol and grouping commas are exactly what the US currency format expects.

    Explanation

    A currency formatter's parse is the inverse of its format: it accepts its own currency symbol and grouping and decimal separators and returns a numeric value. Reading the parsed number as a double and printing it shows no trailing zeros, because a double stores no significant-trailing-zero information, so 1234.50 and 1234.5 are the same double.

Practise all 14 Localization questions

OCP Java SE 25 has the full set, inside timed mock exams that mirror real exam conditions — every question with a worked explanation.

Open OCP Java SE 25

Other topics in this pack