解决方案 »

  1.   

    你查看下API就清楚了;
    再有是了解下UTF-16编码的规则,如BE和LE的区别;也可测试下:前面的两个字节其实是FE FF,表示高字节在前;
      

  2.   

    忘说是 查看Character类;示例下:public class CharacterDemo { public static void main(String[] args) throws IOException { String str = "我";
    for(int i=0;i<str.length();i++){
    Character ch = str.charAt(i);
    System.out.println(ch+"   "+ch.SIZE+"   "+String.valueOf(ch).getBytes("UNICODE").length);
    System.out.println(byteToHex(String.valueOf(ch).getBytes("UNICODE")));
    }
    }
    public static String byteToHex(byte [] bytes){
    StringBuilder sb = new StringBuilder(4);
    for (int b : bytes) {
    sb.append(Integer.toHexString(b & 0x00FF | 0xFF00).substring(2, 4).toUpperCase());
    sb.append(" ");
    }
    return sb.toString(); }
    }
      

  3.   

    CharsetEncoder  中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法
        private static class Encoder extends UnicodeEncoder
        {        public Encoder(Charset charset)
            {
                super(charset, 0, true);
            }
        }我想问一下 从 encodeLoop()-------> Encoder函数  这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
    public abstract class UnicodeEncoder extends CharsetEncoder 中的方法   protected UnicodeEncoder(Charset charset, int i, boolean flag)
        {
            super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
                -3, -1
            }) : (new byte[] {
                -1, -3
            }));
            usesMark = needsMark = flag;
            byteOrder = i;
        }
    中完成
      

  4.   

    为毛 jdk源码中没有 sun.nio.cs.UnicodeEncoder 的源码?
      

  5.   

    CharsetEncoder  中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法
        private static class Encoder extends UnicodeEncoder
        {        public Encoder(Charset charset)
            {
                super(charset, 0, true);
            }
        }我想问一下 从 encodeLoop()-------> Encoder函数  这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
    public abstract class UnicodeEncoder extends CharsetEncoder 中的方法   protected UnicodeEncoder(Charset charset, int i, boolean flag)
        {
            super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
                -3, -1
            }) : (new byte[] {
                -1, -3
            }));
            usesMark = needsMark = flag;
            byteOrder = i;
        }
    中完成
    我对源代码的态度是:找关键的看,有目的的看,看得懂就看;你上面说的源代码在sun开头的包中,而sun开头的包是不包含在JDK自带的那个src.zip中的;你需要自己去下载;或下载个反编译的工具也是可以的;至于你上面说的源代码不明白,也简单说下:
    其实你不需要关心UnicodeEncoder这个构造器方法;
    关键就是上面提到的 encodeLoop(in, out),这个方法才是关键的;
    这里有个参数 in 和 out,那其实简化就是in表示输入,out表示要输出的(out是ByteBuffer,in是CharBufer,从参数类型也可以看出);而且你也知道在CharsetEncoder类中,encodeLoop是protected abstract的,那自然是子类实现了; 
    你找到了UTF_16,但它是Charset的子类,但它定义了一个内部类 Encoder extends UnicodeEncoder ,而UnicodeEncoder有个encodeLoop() ,看到这里其它的可以忽略了吧,直接查看UnicodeEncoder 的 encodeLoop(); 
    如果是反编译的话,你会看到UnicodeEncoder 的 put方法是这样:
     private void put(char paramChar, ByteBuffer paramByteBuffer) {
        if (this.byteOrder == 0) {
          paramByteBuffer.put((byte)(paramChar >> '\b'));
          paramByteBuffer.put((byte)(paramChar & 0xFF));
        } else {
          paramByteBuffer.put((byte)(paramChar & 0xFF));
          paramByteBuffer.put((byte)(paramChar >> '\b'));
        }  }它的encodeLoop方法前面是这样的:
    protected CoderResult encodeLoop(CharBuffer paramCharBuffer, ByteBuffer paramByteBuffer)
      {
        int i = paramCharBuffer.position();    if (this.needsMark) {
          if (paramByteBuffer.remaining() < 2)
            return CoderResult.OVERFLOW;
          put(65279, paramByteBuffer);      this.needsMark = false;
        }
        try
        {
    ...   ....
    看到这里,需要考虑下那个needsMark, 你上面提到的UTF_16 类中的内部类Encoder 会 super(charset, 0, true); 而这个needsMark = flag;  所以很显然是true了;
    由于编译器对于一些常量是内嵌的,反编译后那个put方法了有点难理解,但可以自己动手测试下就清楚了:
    如:
    byte[] b1 = {((byte)(65279 >> '\b'))};
    byte[] b2 = {((byte)(65279 & 0xFF))};
    System.out.print(byteToHex(b1) + ' ');
    System.out.print(byteToHex(b2));
    System.out.println();

    byte[] b11 = {((byte)('我' >> '\b'))};
    byte[] b22 = {((byte)('我' & 0xFF))};
    System.out.print(byteToHex(b11) + ' ');
    System.out.print(byteToHex(b22));
    System.out.println();
    其实put方法中的:if (this.byteOrder == 0) 表示的是高字节在前的意思;如果你是附加源代码的方式查看,那就非常的明确了;
      

  6.   

    CharsetEncoder  中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法
        private static class Encoder extends UnicodeEncoder
        {        public Encoder(Charset charset)
            {
                super(charset, 0, true);
            }
        }我想问一下 从 encodeLoop()-------> Encoder函数  这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
    public abstract class UnicodeEncoder extends CharsetEncoder 中的方法   protected UnicodeEncoder(Charset charset, int i, boolean flag)
        {
            super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
                -3, -1
            }) : (new byte[] {
                -1, -3
            }));
            usesMark = needsMark = flag;
            byteOrder = i;
        }
    中完成
    当然,如果你纠结于此,可以看下StringCoding的内部类StringEncoder 的 encode方法:
     static byte[] encode(String charsetName, char[] ca, int off, int len)
    throws UnsupportedEncodingException
        {
    StringEncoder se = (StringEncoder)deref(encoder);
    String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
      if ((se == null) || !(csn.equals(se.requestedCharsetName())
            || csn.equals(se.charsetName()))) {
        se = null;
        try {
    Charset cs = lookupCharset(csn);
    if (cs != null)
        se = new StringEncoder(cs, csn);
        } catch (IllegalCharsetNameException x) {}
        if (se == null)
                    throw new UnsupportedEncodingException (csn);
        set(encoder, se);
    }
    return se.encode(ca, off, len);
        }当调用new StringEncoder(cs, csn)时,就会调用初始化 Charset 的 Encoder --> cs.newEncoder();
    这样很清楚了吧;