java的NumberFormat、DecimalFormat、MessageFormat类源码详解

java的NumberFormat、DecimalFormat、MessageFormat类源码详解

NumberFormat类的定义

public abstract class NumberFormat extends Format  {

    protected NumberFormat() {
    }

    @Override
    public StringBuffer format(Object number,
                               StringBuffer toAppendTo,
                               FieldPosition pos) {
        if (number instanceof Long || number instanceof Integer ||
            number instanceof Short || number instanceof Byte ||
            number instanceof AtomicInteger || number instanceof AtomicLong ||
            (number instanceof BigInteger &&
             ((BigInteger)number).bitLength() < 64)) {
            return format(((Number)number).longValue(), toAppendTo, pos);
        } else if (number instanceof Number) {
            return format(((Number)number).doubleValue(), toAppendTo, pos);
        } else {
            throw new IllegalArgumentException("Cannot format given Object as a Number");
        }
    }

    @Override
    public final Object parseObject(String source, ParsePosition pos) {
        return parse(source, pos);
    }

    public final String format(double number) {
        // Use fast-path for double result if that works
        String result = fastFormat(number);
        if (result != null)
            return result;

        return format(number, new StringBuffer(),
                      DontCareFieldPosition.INSTANCE).toString();
    }


    String fastFormat(double number) { return null; }

    public final String format(long number) {
        return format(number, new StringBuffer(),
                      DontCareFieldPosition.INSTANCE).toString();
    }

    public abstract StringBuffer format(double number,
                                        StringBuffer toAppendTo,
                                        FieldPosition pos);

    public abstract StringBuffer format(long number,
                                        StringBuffer toAppendTo,
                                        FieldPosition pos);

    public abstract Number parse(String source, ParsePosition parsePosition);

    public Number parse(String source) throws ParseException {
        ParsePosition parsePosition = new ParsePosition(0);
        Number result = parse(source, parsePosition);
        if (parsePosition.index == 0) {
            throw new ParseException("Unparseable number: \"" + source + "\"",
                                     parsePosition.errorIndex);
        }
        return result;
    }

    public boolean isParseIntegerOnly() {
        return parseIntegerOnly;
    }

    public void setParseIntegerOnly(boolean value) {
        parseIntegerOnly = value;
    }

    //============== Locale Stuff =====================
    public final static NumberFormat getInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
    }

    public static NumberFormat getInstance(Locale inLocale) {
        return getInstance(inLocale, NUMBERSTYLE);
    }

    public final static NumberFormat getNumberInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
    }

    public static NumberFormat getNumberInstance(Locale inLocale) {
        return getInstance(inLocale, NUMBERSTYLE);
    }

    public final static NumberFormat getIntegerInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), INTEGERSTYLE);
    }

    public static NumberFormat getIntegerInstance(Locale inLocale) {
        return getInstance(inLocale, INTEGERSTYLE);
    }

    public final static NumberFormat getCurrencyInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), CURRENCYSTYLE);
    }

    public static NumberFormat getCurrencyInstance(Locale inLocale) {
        return getInstance(inLocale, CURRENCYSTYLE);
    }

    public final static NumberFormat getPercentInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), PERCENTSTYLE);
    }

    public static NumberFormat getPercentInstance(Locale inLocale) {
        return getInstance(inLocale, PERCENTSTYLE);
    }

    /*public*/ final static NumberFormat getScientificInstance() {
        return getInstance(Locale.getDefault(Locale.Category.FORMAT), SCIENTIFICSTYLE);
    }

    /*public*/ static NumberFormat getScientificInstance(Locale inLocale) {
        return getInstance(inLocale, SCIENTIFICSTYLE);
    }

    public static Locale[] getAvailableLocales() {
        LocaleServiceProviderPool pool =
            LocaleServiceProviderPool.getPool(NumberFormatProvider.class);
        return pool.getAvailableLocales();
    }

    @Override
    public int hashCode() {
        return maximumIntegerDigits * 37 + maxFractionDigits;
        // just enough fields for a reasonable distribution
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        NumberFormat other = (NumberFormat) obj;
        return (maximumIntegerDigits == other.maximumIntegerDigits
            && minimumIntegerDigits == other.minimumIntegerDigits
            && maximumFractionDigits == other.maximumFractionDigits
            && minimumFractionDigits == other.minimumFractionDigits
            && groupingUsed == other.groupingUsed
            && parseIntegerOnly == other.parseIntegerOnly);
    }

    @Override
    public Object clone() {
        NumberFormat other = (NumberFormat) super.clone();
        return other;
    }
}

java的NumberFormat、DecimalFormat、MessageFormat类源码详解_第1张图片

import java.text.* ; 
public class NumberFormatDemo01{ 
  public static void main(String args[]){ 
    NumberFormat nf = null ;    // 声明一个NumberFormat对象 
    nf = NumberFormat.getInstance() ;  // 得到默认的数字格式化显示 
    System.out.println("格式化之后的数字:" + nf.format(10000000)) ; 
    System.out.println("格式化之后的数字:" + nf.format(1000.345)) ; 
  } 
}; 

import java.text.NumberFormat;

1。Decimalformat df1 = new Decimalformat("####.000"); 
   
      System.out.println(df1.format(1234.56));

     显示:1234.560

2。NumberFormat nf   =   NumberFormat.getPercentInstance();     
  // nf.setMinimumFractionDigits( 2 );        保留到小数点后几位        显示:47.00%

  System.out.println(nf.format(0.47));

     显示:47%

     (法二)

     DecimalFormat df1 = new DecimalFormat("##.00%");    //##.00%   百分比格式,后面不足2位的用0补齐
     baifenbi= df1.format(fen);  

     显示:47.00%

3。DecimalFormat   df   =   new   DecimalFormat("###,##0.00");

      System.out.println(nf.format(24.7));

     显示:24.70

      System.out.println(nf.format(23123.47));

    显示:123,23.47

补充:0.00、0.01; 0.00%、0.12%这样的数据,如果按照上面的格式可能会造成数据显示成:.00、.01; .00%、.12%,怎么办呢?只要把格式改成:

    DecimalFormat df1 = new DecimalFormat("0.00");    
    DecimalFormat df2 = new DecimalFormat("0.00%");

    df1.formatI(number);df2.formatI(number);

     显示:0.00、0.01; 0.00%、0.12%

public class Test {
 public static void main(String[] args) {
  Double myNumber=23323.3323232323;
  Double test=0.3434;
  //getInstance() 
  //返回当前缺省语言环境的缺省数值格式。
  String myString = NumberFormat.getInstance().format(myNumber);
  System.out.println(myString);
  //getCurrencyInstance()返回当前缺省语言环境的通用格式
  myString = NumberFormat.getCurrencyInstance().format(myNumber); 
  System.out.println(myString);
  //getNumberInstance() 返回当前缺省语言环境的通用数值格式。 
  myString = NumberFormat.getNumberInstance().format(myNumber); 
  System.out.println(myString);
  //getPercentInstance()  返回当前缺省语言环境的百分比格式。
  myString = NumberFormat.getPercentInstance().format(test); 
  System.out.println(myString);
  //setMaximumFractionDigits(int) 设置数值的小数部分允许的最大位数。 
  //setMaximumIntegerDigits(int)  设置数值的整数部分允许的最大位数。 
  //setMinimumFractionDigits(int) 设置数值的小数部分允许的最小位数。 
  //setMinimumIntegerDigits(int)  设置数值的整数部分允许的最小位数.
  NumberFormat format = NumberFormat.getInstance();
  format.setMinimumFractionDigits( 3 );
  format.setMaximumFractionDigits(5);
  format.setMaximumIntegerDigits( 10 );
  format.setMinimumIntegerDigits(0);
  System.out.println(format.format(2132323213.23266666666));
 }

}

结果为:
23,323.332
¥23,323.33
23,323.332
34%
2,132,323,213.23267

 

MessageFormat

public class MessageFormat extends Format {

    private static final long serialVersionUID = 6479157306784022952L;

    public MessageFormat(String pattern) {
        this.locale = Locale.getDefault(Locale.Category.FORMAT);
        applyPattern(pattern);
    }

    public MessageFormat(String pattern, Locale locale) {
        this.locale = locale;
        applyPattern(pattern);
    }

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    public Locale getLocale() {
        return locale;
    }

    @SuppressWarnings("fallthrough") // fallthrough in switch is expected, suppress it
    public void applyPattern(String pattern) {
            StringBuilder[] segments = new StringBuilder[4];
            // Allocate only segments[SEG_RAW] here. The rest are
            // allocated on demand.
            segments[SEG_RAW] = new StringBuilder();

            int part = SEG_RAW;
            int formatNumber = 0;
            boolean inQuote = false;
            int braceStack = 0;
            maxOffset = -1;
            for (int i = 0; i < pattern.length(); ++i) {
                char ch = pattern.charAt(i);
                if (part == SEG_RAW) {
                    if (ch == '\'') {
                        if (i + 1 < pattern.length()
                            && pattern.charAt(i+1) == '\'') {
                            segments[part].append(ch);  // handle doubles
                            ++i;
                        } else {
                            inQuote = !inQuote;
                        }
                    } else if (ch == '{' && !inQuote) {
                        part = SEG_INDEX;
                        if (segments[SEG_INDEX] == null) {
                            segments[SEG_INDEX] = new StringBuilder();
                        }
                    } else {
                        segments[part].append(ch);
                    }
                } else  {
                    if (inQuote) {              // just copy quotes in parts
                        segments[part].append(ch);
                        if (ch == '\'') {
                            inQuote = false;
                        }
                    } else {
                        switch (ch) {
                        case ',':
                            if (part < SEG_MODIFIER) {
                                if (segments[++part] == null) {
                                    segments[part] = new StringBuilder();
                                }
                            } else {
                                segments[part].append(ch);
                            }
                            break;
                        case '{':
                            ++braceStack;
                            segments[part].append(ch);
                            break;
                        case '}':
                            if (braceStack == 0) {
                                part = SEG_RAW;
                                makeFormat(i, formatNumber, segments);
                                formatNumber++;
                                // throw away other segments
                                segments[SEG_INDEX] = null;
                                segments[SEG_TYPE] = null;
                                segments[SEG_MODIFIER] = null;
                            } else {
                                --braceStack;
                                segments[part].append(ch);
                            }
                            break;
                        case ' ':
                            // Skip any leading space chars for SEG_TYPE.
                            if (part != SEG_TYPE || segments[SEG_TYPE].length() > 0) {
                                segments[part].append(ch);
                            }
                            break;
                        case '\'':
                            inQuote = true;
                            // fall through, so we keep quotes in other parts
                        default:
                            segments[part].append(ch);
                            break;
                        }
                    }
                }
            }
            if (braceStack == 0 && part != 0) {
                maxOffset = -1;
                throw new IllegalArgumentException("Unmatched braces in the pattern.");
            }
            this.pattern = segments[0].toString();
    }

    public String toPattern() {
        // later, make this more extensible
        int lastOffset = 0;
        StringBuilder result = new StringBuilder();
        for (int i = 0; i <= maxOffset; ++i) {
            copyAndFixQuotes(pattern, lastOffset, offsets[i], result);
            lastOffset = offsets[i];
            result.append('{').append(argumentNumbers[i]);
            Format fmt = formats[i];
            if (fmt == null) {
                // do nothing, string format
            } else if (fmt instanceof NumberFormat) {
                if (fmt.equals(NumberFormat.getInstance(locale))) {
                    result.append(",number");
                } else if (fmt.equals(NumberFormat.getCurrencyInstance(locale))) {
                    result.append(",number,currency");
                } else if (fmt.equals(NumberFormat.getPercentInstance(locale))) {
                    result.append(",number,percent");
                } else if (fmt.equals(NumberFormat.getIntegerInstance(locale))) {
                    result.append(",number,integer");
                } else {
                    if (fmt instanceof DecimalFormat) {
                        result.append(",number,").append(((DecimalFormat)fmt).toPattern());
                    } else if (fmt instanceof ChoiceFormat) {
                        result.append(",choice,").append(((ChoiceFormat)fmt).toPattern());
                    } else {
                        // UNKNOWN
                    }
                }
            } else if (fmt instanceof DateFormat) {
                int index;
                for (index = MODIFIER_DEFAULT; index < DATE_TIME_MODIFIERS.length; index++) {
                    DateFormat df = DateFormat.getDateInstance(DATE_TIME_MODIFIERS[index],
                                                               locale);
                    if (fmt.equals(df)) {
                        result.append(",date");
                        break;
                    }
                    df = DateFormat.getTimeInstance(DATE_TIME_MODIFIERS[index],
                                                    locale);
                    if (fmt.equals(df)) {
                        result.append(",time");
                        break;
                    }
                }
                if (index >= DATE_TIME_MODIFIERS.length) {
                    if (fmt instanceof SimpleDateFormat) {
                        result.append(",date,").append(((SimpleDateFormat)fmt).toPattern());
                    } else {
                        // UNKNOWN
                    }
                } else if (index != MODIFIER_DEFAULT) {
                    result.append(',').append(DATE_TIME_MODIFIER_KEYWORDS[index]);
                }
            } else {
                //result.append(", unknown");
            }
            result.append('}');
        }
        copyAndFixQuotes(pattern, lastOffset, pattern.length(), result);
        return result.toString();
    }

   public final StringBuffer format(Object[] arguments, StringBuffer result,
                                     FieldPosition pos)
    {
        return subformat(arguments, result, pos, null);
    }

    public static String format(String pattern, Object ... arguments) {
        MessageFormat temp = new MessageFormat(pattern);
        return temp.format(arguments);
    }

    // Overrides
    public final StringBuffer format(Object arguments, StringBuffer result,
                                     FieldPosition pos)
    {
        return subformat((Object[]) arguments, result, pos, null);
    }

    public Object[] parse(String source, ParsePosition pos) {
        if (source == null) {
            Object[] empty = {};
            return empty;
        }

        int maximumArgumentNumber = -1;
        for (int i = 0; i <= maxOffset; i++) {
            if (argumentNumbers[i] > maximumArgumentNumber) {
                maximumArgumentNumber = argumentNumbers[i];
            }
        }
        Object[] resultArray = new Object[maximumArgumentNumber + 1];

        int patternOffset = 0;
        int sourceOffset = pos.index;
        ParsePosition tempStatus = new ParsePosition(0);
        for (int i = 0; i <= maxOffset; ++i) {
            // match up to format
            int len = offsets[i] - patternOffset;
            if (len == 0 || pattern.regionMatches(patternOffset,
                                                  source, sourceOffset, len)) {
                sourceOffset += len;
                patternOffset += len;
            } else {
                pos.errorIndex = sourceOffset;
                return null; // leave index as is to signal error
            }

            // now use format
            if (formats[i] == null) {   // string format
                // if at end, use longest possible match
                // otherwise uses first match to intervening string
                // does NOT recursively try all possibilities
                int tempLength = (i != maxOffset) ? offsets[i+1] : pattern.length();

                int next;
                if (patternOffset >= tempLength) {
                    next = source.length();
                }else{
                    next = source.indexOf(pattern.substring(patternOffset, tempLength),
                                          sourceOffset);
                }

                if (next < 0) {
                    pos.errorIndex = sourceOffset;
                    return null; // leave index as is to signal error
                } else {
                    String strValue= source.substring(sourceOffset,next);
                    if (!strValue.equals("{"+argumentNumbers[i]+"}"))
                        resultArray[argumentNumbers[i]]
                            = source.substring(sourceOffset,next);
                    sourceOffset = next;
                }
            } else {
                tempStatus.index = sourceOffset;
                resultArray[argumentNumbers[i]]
                    = formats[i].parseObject(source,tempStatus);
                if (tempStatus.index == sourceOffset) {
                    pos.errorIndex = sourceOffset;
                    return null; // leave index as is to signal error
                }
                sourceOffset = tempStatus.index; // update
            }
        }
        int len = pattern.length() - patternOffset;
        if (len == 0 || pattern.regionMatches(patternOffset,
                                              source, sourceOffset, len)) {
            pos.index = sourceOffset + len;
        } else {
            pos.errorIndex = sourceOffset;
            return null; // leave index as is to signal error
        }
        return resultArray;
    }

    public Object[] parse(String source) throws ParseException {
        ParsePosition pos  = new ParsePosition(0);
        Object[] result = parse(source, pos);
        if (pos.index == 0)  // unchanged, returned object is null
            throw new ParseException("MessageFormat parse error!", pos.errorIndex);

        return result;
    }

    public Object parseObject(String source, ParsePosition pos) {
        return parse(source, pos);
    }

    public Object clone() {
        MessageFormat other = (MessageFormat) super.clone();

        // clone arrays. Can't do with utility because of bug in Cloneable
        other.formats = formats.clone(); // shallow clone
        for (int i = 0; i < formats.length; ++i) {
            if (formats[i] != null)
                other.formats[i] = (Format)formats[i].clone();
        }
        // for primitives or immutables, shallow clone is enough
        other.offsets = offsets.clone();
        other.argumentNumbers = argumentNumbers.clone();

        return other;
    }

    public boolean equals(Object obj) {
        if (this == obj)                      // quick check
            return true;
        if (obj == null || getClass() != obj.getClass())
            return false;
        MessageFormat other = (MessageFormat) obj;
        return (maxOffset == other.maxOffset
                && pattern.equals(other.pattern)
                && ((locale != null && locale.equals(other.locale))
                 || (locale == null && other.locale == null))
                && Arrays.equals(offsets,other.offsets)
                && Arrays.equals(argumentNumbers,other.argumentNumbers)
                && Arrays.equals(formats,other.formats));
    }

    public static class Field extends Format.Field {

        // Proclaim serial compatibility with 1.4 FCS
        private static final long serialVersionUID = 7899943957617360810L;

        protected Field(String name) {
            super(name);
        }

        protected Object readResolve() throws InvalidObjectException {
            if (this.getClass() != MessageFormat.Field.class) {
                throw new InvalidObjectException("subclass didn't correctly implement readResolve");
            }

            return ARGUMENT;
        }

        //
        // The constants
        //
        public final static Field ARGUMENT =
                           new Field("message argument field");
    }
}

为什么要使用静态内部类

class Company {

    private String theCEO = "stupid";
    private static String companyName = "STUPID COM";

    // 1
    static class Employee {
        public Employee() {
            System.out.println("company name - " + companyName);
            // 2
            //System.out.println("CEO - " + theCEO);
        }
    }

    public Company(){
        System.out.println("Company object is created");
    }
}

public class Main {

    public static void main(String[] args) {
//        Company company = new Company();
//        Company.Employee employee = company.new Employee();

        // 3
        Company.Employee employee = new Company.Employee();
    }
}

如果内部类不是静态的。要用这个内部类就必须先初始化包裹类。也是,如果不初始化出来对应的包裹类,内部类对象怎么能访问这些包裹类对象的非静态实例对象呢。

  1. static,员工类变成静态内部类。
  2. 静态内部类不能再访问包裹类的非静态成员。
  3. 看起来正常的初始化方法:new Company.Employee()

一般来说,内部类不需要访问包裹类的非静态成员的时候。或者只是做一个工具给外部调用,而这些工具需要按照功能区分为的时候使用静态内部类。

 

FormatElement:
         { ArgumentIndex }
         { ArgumentIndex , FormatType }
         { ArgumentIndex , FormatType , FormatStyle }

FormatType: 
         number
         date
         time
         choice(需要使用ChoiceFormat)
FormatStyle:
         short
         medium
         long
         full
         integer
         currency
         percent
         SubformatPattern(子模式)

{0}、{1,number,short}、{2,number,#.#}属于FormatElement,0,1,2是ArgumentIndex

{1,number,short}里面的number属于FormatType,short则属于FormatStyle

{1,number,#.#}里面的#.#就属于子格式模式


import java.text.MessageFormat;
 
String str = "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}{16}";
Object[] array = new Object[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q"};
String value = MessageFormat.format(str, array);
System.out.println(value); // ABCDEFGHIJKLMNOPQ
 
 
String message = "oh, {0} is a person";
Object[] array = new Object[]{"ZhangSan"};
String value = MessageFormat.format(message, array);
System.out.println(value); // oh, ZhangSan is a person
 
 
String message = "oh, {0,number,#.#} is a number";
Object[] array = new Object[]{new Double(3.1415)};
String value = MessageFormat.format(message, array);
System.out.println(value); // oh, 3.1 is a number
 
 
// MessageFormat的format方法源码
public static String format(String pattern, Object ... arguments) 
{
    MessageFormat temp = new MessageFormat(pattern);
    return temp.format(arguments);
}

对字符串的匹配比较智能

String str = "{0} | {1} | {0} | {1}";
Object[] array = new Object[] { "A", "B" };
String value = MessageFormat.format(str, array);
System.out.println(value); // A | B | A | B
        StringBuilder sb=new StringBuilder();
        sb.append("    insert into test_tb (");
        sb.append("        createTime, ");
        sb.append("        datefrom, ");
        sb.append("        dateto, ");
        sb.append("        name, ");
        sb.append("        intranetid, ");
        sb.append("        actualhour, ");
        sb.append("        planhour, ");
        sb.append("        status");
        sb.append("    ) values (");
        sb.append("        ''{0}'',");
        sb.append("        ''{1}'',");
        sb.append("        ''{2}'',");
        sb.append("        ''{3}'',");
        sb.append("        ''{4}'',");
        sb.append("        ''{5}'',");
        sb.append("        ''{6}'',");
        sb.append("        ''{7}''");
        sb.append("    )");
        String result=sb.toString();
        
        Object[] arr={createTime,datefrom,dateto,name,intranetid,actualhour,planhour,status};
        String sql=MessageFormat.format(result, arr);

 

你可能感兴趣的:(Java源码)