diff --git a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java index 0a7c3e20a2e..39cfd1c52a0 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java @@ -95,9 +95,7 @@ public class MeasureFormat extends UFormat { // Generated by serialver from JDK 1.4.1_01 static final long serialVersionUID = -7182021401701778240L; - // NumberFormat is known to lack thread-safety, all access to this - // field must be synchronized. - private final transient NumberFormat numberFormat; + private final transient ImmutableNumberFormat numberFormat; private final transient FormatWidth length; @@ -190,7 +188,8 @@ public class MeasureFormat extends UFormat { unitToStyleToCountToFormat = loadLocaleData(locale, rules); localeToUnitToStyleToCountToFormat.put(locale, unitToStyleToCountToFormat); } - return new MeasureFormat(locale, width, format, rules, unitToStyleToCountToFormat); + return new MeasureFormat( + locale, width, new ImmutableNumberFormat(format), rules, unitToStyleToCountToFormat); } /** @@ -421,9 +420,7 @@ public class MeasureFormat extends UFormat { * @provisional */ public NumberFormat getNumberFormat() { - synchronized (numberFormat) { - return (NumberFormat) numberFormat.clone(); - } + return numberFormat.get(); } /** @@ -456,7 +453,7 @@ public class MeasureFormat extends UFormat { return new MeasureFormat( getLocale(), this.length, - (NumberFormat) format.clone(), + new ImmutableNumberFormat(format), this.rules, this.unitToStyleToCountToFormat); } @@ -464,7 +461,7 @@ public class MeasureFormat extends UFormat { private MeasureFormat( ULocale locale, FormatWidth width, - NumberFormat format, + ImmutableNumberFormat format, PluralRules rules, Map>> unitToStyleToCountToFormat) { setLocale(locale, locale); @@ -588,22 +585,17 @@ public class MeasureFormat extends UFormat { } - private static boolean objEquals(Object lhs, Object rhs) { - return lhs == null ? rhs == null : lhs.equals(rhs); - - } - Object toTimeUnitProxy() { - return new MeasureProxy(getLocale(), length, numberFormat, TIME_UNIT_FORMAT); + return new MeasureProxy(getLocale(), length, numberFormat.get(), TIME_UNIT_FORMAT); } Object toCurrencyProxy() { - return new MeasureProxy(getLocale(), length, numberFormat, CURRENCY_FORMAT); + return new MeasureProxy(getLocale(), length, numberFormat.get(), CURRENCY_FORMAT); } private Object writeReplace() throws ObjectStreamException { return new MeasureProxy( - getLocale(), length, numberFormat, MEASURE_FORMAT); + getLocale(), length, numberFormat.get(), MEASURE_FORMAT); } static class MeasureProxy implements Externalizable { @@ -712,4 +704,22 @@ public class MeasureFormat extends UFormat { throw new IllegalStateException("Unable to serialize Format Width " + fw); } } + + // Wrapper around NumberFormat that provides immutability and thread-safety. + private static final class ImmutableNumberFormat { + private NumberFormat nf; + + public ImmutableNumberFormat(NumberFormat nf) { + this.nf = (NumberFormat) nf.clone(); + } + + public synchronized NumberFormat get() { + return (NumberFormat) nf.clone(); + } + + public synchronized StringBuffer format( + Number n, StringBuffer buffer, FieldPosition pos) { + return nf.format(n, buffer, pos); + } + } }