📄 choiceformat.java
字号:
/* * @(#)ChoiceFormat.java 1.32 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved * * The original version of this source code and documentation is copyrighted * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These * materials are provided under terms of a License Agreement between Taligent * and Sun. This technology is protected by multiple US and International * patents. This notice and attribution to Taligent may not be removed. * Taligent is a registered trademark of Taligent, Inc. * */package java.text;import java.io.InvalidObjectException;import java.io.IOException;import java.io.ObjectInputStream;import sun.text.Utility;/** * A <code>ChoiceFormat</code> allows you to attach a format to a range of numbers. * It is generally used in a <code>MessageFormat</code> for handling plurals. * The choice is specified with an ascending list of doubles, where each item * specifies a half-open interval up to the next item: * <blockquote> * <pre> * X matches j if and only if limit[j] <= X < limit[j+1] * </pre> * </blockquote> * If there is no match, then either the first or last index is used, depending * on whether the number (X) is too low or too high. If the limit array is not * in ascending order, the results of formatting will be incorrect. ChoiceFormat * also accepts <code>\u221E</code> as equivalent to infinity(INF). * * <p> * <strong>Note:</strong> * <code>ChoiceFormat</code> differs from the other <code>Format</code> * classes in that you create a <code>ChoiceFormat</code> object with a * constructor (not with a <code>getInstance</code> style factory * method). The factory methods aren't necessary because <code>ChoiceFormat</code> * doesn't require any complex setup for a given locale. In fact, * <code>ChoiceFormat</code> doesn't implement any locale specific behavior. * * <p> * When creating a <code>ChoiceFormat</code>, you must specify an array of formats * and an array of limits. The length of these arrays must be the same. * For example, * <ul> * <li> * <em>limits</em> = {1,2,3,4,5,6,7}<br> * <em>formats</em> = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"} * <li> * <em>limits</em> = {0, 1, ChoiceFormat.nextDouble(1)}<br> * <em>formats</em> = {"no files", "one file", "many files"}<br> * (<code>nextDouble</code> can be used to get the next higher double, to * make the half-open interval.) * </ul> * * <p> * Here is a simple example that shows formatting and parsing: * <blockquote> * <pre> * double[] limits = {1,2,3,4,5,6,7}; * String[] monthNames = {"Sun","Mon","Tue","Wed","Thur","Fri","Sat"}; * ChoiceFormat form = new ChoiceFormat(limits, monthNames); * ParsePosition status = new ParsePosition(0); * for (double i = 0.0; i <= 8.0; ++i) { * status.setIndex(0); * System.out.println(i + " -> " + form.format(i) + " -> " * + form.parse(form.format(i),status)); * } * </pre> * </blockquote> * Here is a more complex example, with a pattern format: * <blockquote> * <pre> * double[] filelimits = {0,1,2}; * String[] filepart = {"are no files","is one file","are {2} files"}; * ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart); * Format[] testFormats = {fileform, null, NumberFormat.getInstance()}; * MessageFormat pattform = new MessageFormat("There {0} on {1}"); * pattform.setFormats(testFormats); * Object[] testArgs = {null, "ADisk", null}; * for (int i = 0; i < 4; ++i) { * testArgs[0] = new Integer(i); * testArgs[2] = testArgs[0]; * System.out.println(pattform.format(testArgs)); * } * </pre> * </blockquote> * <p> * Specifying a pattern for ChoiceFormat objects is fairly straightforward. * For example: * <blockquote> * <pre> * ChoiceFormat fmt = new ChoiceFormat( * "-1#is negative| 0#is zero or fraction | 1#is one |1.0<is 1+ |2#is two |2<is more than 2."); * System.out.println("Formatter Pattern : " + fmt.toPattern()); * * System.out.println("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY)); * System.out.println("Format with -1.0 : " + fmt.format(-1.0)); * System.out.println("Format with 0 : " + fmt.format(0)); * System.out.println("Format with 0.9 : " + fmt.format(0.9)); * System.out.println("Format with 1.0 : " + fmt.format(1)); * System.out.println("Format with 1.5 : " + fmt.format(1.5)); * System.out.println("Format with 2 : " + fmt.format(2)); * System.out.println("Format with 2.1 : " + fmt.format(2.1)); * System.out.println("Format with NaN : " + fmt.format(Double.NaN)); * System.out.println("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY)); * </pre> * </blockquote> * And the output result would be like the following: * <pre> * <blockquote> * Format with -INF : is negative * Format with -1.0 : is negative * Format with 0 : is zero or fraction * Format with 0.9 : is zero or fraction * Format with 1.0 : is one * Format with 1.5 : is 1+ * Format with 2 : is two * Format with 2.1 : is more than 2. * Format with NaN : is negative * Format with +INF : is more than 2. * </pre> * </blockquote> * * <h4><a name="synchronization">Synchronization</a></h4> * * <p> * Choice formats are not synchronized. * It is recommended to create separate format instances for each thread. * If multiple threads access a format concurrently, it must be synchronized * externally. * * * @see DecimalFormat * @see MessageFormat * @version 1.22 09/21/98 * @author Mark Davis */public class ChoiceFormat extends NumberFormat { /** * Sets the pattern. * @param newPattern See the class description. */ public void applyPattern(String newPattern) { StringBuffer[] segments = new StringBuffer[2]; for (int i = 0; i < segments.length; ++i) { segments[i] = new StringBuffer(); } double[] newChoiceLimits = new double[30]; String[] newChoiceFormats = new String[30]; int count = 0; int part = 0; double startValue = 0; double oldStartValue = Double.NaN; boolean inQuote = false; for (int i = 0; i < newPattern.length(); ++i) { char ch = newPattern.charAt(i); if (ch=='\'') { // Check for "''" indicating a literal quote if ((i+1)<newPattern.length() && newPattern.charAt(i+1)==ch) { segments[part].append(ch); ++i; } else { inQuote = !inQuote; } } else if (inQuote) { segments[part].append(ch); } else if (ch == '<' || ch == '#' || ch == '\u2264') { if (segments[0].equals("")) { throw new IllegalArgumentException(); } try { String tempBuffer = segments[0].toString(); if (tempBuffer.equals("\u221E")) { startValue = Double.POSITIVE_INFINITY; } else if (tempBuffer.equals("-\u221E")) { startValue = Double.NEGATIVE_INFINITY; } else { startValue = Double.valueOf(segments[0].toString()).doubleValue(); } } catch (Exception e) { throw new IllegalArgumentException(); } if (ch == '<' && startValue != Double.POSITIVE_INFINITY && startValue != Double.NEGATIVE_INFINITY) { startValue = nextDouble(startValue); } if (startValue <= oldStartValue) { throw new IllegalArgumentException(); } segments[0].setLength(0); part = 1; } else if (ch == '|') { if (count == newChoiceLimits.length) { newChoiceLimits = doubleArraySize(newChoiceLimits); newChoiceFormats = doubleArraySize(newChoiceFormats); } newChoiceLimits[count] = startValue; newChoiceFormats[count] = segments[1].toString(); ++count; oldStartValue = startValue; segments[1].setLength(0); part = 0; } else { segments[part].append(ch); } } // clean up last one if (part == 1) { if (count == newChoiceLimits.length) { newChoiceLimits = doubleArraySize(newChoiceLimits); newChoiceFormats = doubleArraySize(newChoiceFormats); } newChoiceLimits[count] = startValue; newChoiceFormats[count] = segments[1].toString(); ++count; } choiceLimits = new double[count]; System.arraycopy(newChoiceLimits, 0, choiceLimits, 0, count); choiceFormats = new String[count]; System.arraycopy(newChoiceFormats, 0, choiceFormats, 0, count); } /** * Gets the pattern. */ public String toPattern() { StringBuffer result = new StringBuffer(); for (int i = 0; i < choiceLimits.length; ++i) { if (i != 0) { result.append('|'); } // choose based upon which has less precision // approximate that by choosing the closest one to an integer. // could do better, but it's not worth it. double less = previousDouble(choiceLimits[i]); double tryLessOrEqual = Math.abs(Math.IEEEremainder(choiceLimits[i], 1.0d)); double tryLess = Math.abs(Math.IEEEremainder(less, 1.0d)); if (tryLessOrEqual < tryLess) { result.append(""+choiceLimits[i]); result.append('#'); } else { if (choiceLimits[i] == Double.POSITIVE_INFINITY) { result.append("\u221E"); } else if (choiceLimits[i] == Double.NEGATIVE_INFINITY) { result.append("-\u221E"); } else { result.append(""+less); } result.append('<'); } // Append choiceFormats[i], using quotes if there are special characters. // Single quotes themselves must be escaped in either case. String text = choiceFormats[i]; boolean needQuote = text.indexOf('<') >= 0 || text.indexOf('#') >= 0 || text.indexOf('\u2264') >= 0 || text.indexOf('|') >= 0; if (needQuote) result.append('\''); if (text.indexOf('\'') < 0) result.append(text); else { for (int j=0; j<text.length(); ++j) { char c = text.charAt(j); result.append(c); if (c == '\'') result.append(c); } } if (needQuote) result.append('\''); } return result.toString(); } /** * Constructs with limits and corresponding formats based on the pattern. * @see #applyPattern */ public ChoiceFormat(String newPattern) { applyPattern(newPattern); } /** * Constructs with the limits and the corresponding formats. * @see #setChoices */ public ChoiceFormat(double[] limits, String[] formats) { setChoices(limits, formats); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -