看到Long这个类,颇感亲切,今天研究Long类的几个静态方法。
如果想把long类型数据转换为字节数组byte[ ],使用 Long.toString(l).getBytes()方法,但是这种转换很山寨。所以研究一下ing......
/** * long数据类型转换为byte[] * * 该方法会将long型数据每一位转换为一个字节,long高位在低字节,低位在高字节 */ public byte[] convertLongToByteArray(long l) { return Long.toString(l).getBytes(); }
细心的人会发现这种算法,只是将long数据每一位转换为一个字节,如果你定义long = 12345L,那么就会得到5个字节。如果你定义long =
123456789L,那么就会得到9个字节。思考一下,这样产生的问题是什么?!
yes,long类型数据占有个字节,怎么会5、9呢?你可以测试一把,证明我所说的是否正确!呵呵!
研究一下String类的getBytes方法,其实etBytes调用StringCoding类的方法,将数字转换为字符char,并且使用ISO-8859-1编码,看一下:
static byte[] encode(char[] ca, int off, int len) { String csn = Charset.defaultCharset().name(); try { return encode(csn, ca, off, len); } catch (UnsupportedEncodingException x) { warnUnsupportedCharset(csn); } try { return encode("ISO-8859-1", ca, off, len); } catch (UnsupportedEncodingException x) { // If this code is hit during VM initialization, MessageUtils is // the only way we will be able to get any kind of error message. MessageUtils.err("ISO-8859-1 charset not available: " + x.toString()); // If we can not find ISO-8859-1 (a required encoding) then things // are seriously wrong with the installation. System.exit(1); return null; } }
static byte[] encode(Charset cs, char[] ca, int off, int len) { StringEncoder se = new StringEncoder(cs, cs.name()); char[] c = Arrays.copyOf(ca, ca.length); return se.encode(c, off, len); }
我们知道,数字1对应的Ascii码就是1,但是字符‘1’对应的Ascii码却是31,有图为证:
所以,测试中你会发现1234L变成了49、50、51、52(这是十进制数,对应Ascii码的31、32、33、34)。
当然,如果你愿意的话,getBytes(Charset charset)方法可以指定其他字符编码。
现在,针对上面的“山寨”方法convertLongToByteArray,我需要将字节数组转换为long,看代码:
/** * byte[]数据类型转换为long * * 针对convertLongToByteArray(long l)方法 * * @param buf 字节数组 * @return long */ public Long toLong(byte[] buf) { StringBuffer sb = new StringBuffer(); int len = buf.length; for(int i=0; i<len; i++) { sb.append( Long.toString(buf[i] - 48)); } String res = sb.toString(); Long.valueOf(res); Long.parseLong(res); Long.getLong(res); return Long.valueOf(res); }
将String 转换为long,下面几个方法都可以:
Long.valueOf(String s); Long.parseLong(String s); Long.getLong(String s);
valueOf方法,调用parseLong(String s, int radix)方法,其中参数radix表示基数即何种进制:
public static Long valueOf(String s) throws NumberFormatException { return Long.valueOf(parseLong(s, 10)); }
可见valueOf方法,调用parseLong方法,使用10进制为基数。研究一下parseLong(String s, int radix)源码:
public static long parseLong(String s, int radix) throws NumberFormatException { if (s == null) { throw new NumberFormatException("null"); } if (radix < Character.MIN_RADIX) { throw new NumberFormatException("radix " + radix + " less than Character.MIN_RADIX"); } if (radix > Character.MAX_RADIX) { throw new NumberFormatException("radix " + radix + " greater than Character.MAX_RADIX"); } long result = 0; boolean negative = false; int i = 0, max = s.length(); long limit; long multmin; int digit; if (max > 0) { if (s.charAt(0) == '-') { negative = true; limit = Long.MIN_VALUE; i++; } else { limit = -Long.MAX_VALUE; } if (radix == 10) { multmin = negative ? MULTMIN_RADIX_TEN : N_MULTMAX_RADIX_TEN; } else { multmin = limit / radix; } if (i < max) { digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw NumberFormatException.forInputString(s); } else { result = -digit; } } while (i < max) { // Accumulating negatively avoids surprises near MAX_VALUE digit = Character.digit(s.charAt(i++),radix); if (digit < 0) { throw NumberFormatException.forInputString(s); } if (result < multmin) { throw NumberFormatException.forInputString(s); } result *= radix; if (result < limit + digit) { throw NumberFormatException.forInputString(s); } result -= digit; } } else { throw NumberFormatException.forInputString(s); } if (negative) { if (i > 1) { return result; } else { /* Only got "-" */ throw NumberFormatException.forInputString(s); } } else { return -result; } }
有兴趣可以去看看getLong方法,它本质是调用valueOf方法,而valueOf方法本质是调用parseLong方法,所以在你的代码中应该使用哪个方法,你应该明白啦!
ok,到此为止!
感谢:http://www.asciitable.com/ 提供Ascii码表,另附一张图如下: