bigdecimal转换为long_夯实基础:Byte和各数据类型之间的转换

在Java网络编程中,常需在byte数组和其他数据类型间相互转换,核心是将其他类型数据的每一位转为byte类型。文中给出了short、int、long、float、double与byte数组互转,字符串和十六进制数互转,以及对象序列化和反序列化的相关代码,并提供工具类参考。

在Java的网络编程中传输的经常是byte数组,但我们实际中使用的数据类型可能是任一种数据类型,这就需要在它们之间相互转换,转换的核心在于将其他类型的数据的每一位转换成byte类型的数据。

435fc5c3e0810acfa57ee20de6c22d19.png

下面给出相关的转换代码——

1.short与byte数组的互转

/*** 转换short为byte** @param b* @param s 需要转换的short* @param index*/public static void putShort(byte b[], short s, int index) { b[index + 1] = (byte) (s >> 8); b[index + 0] = (byte) (s >> 0);}/*** 通过byte数组取到short** @param b* @param index 第几位开始取* @return*/public static short getShort(byte[] b, int index) { return (short) (((b[index + 1] << 8) | b[index + 0] & 0xff));}

2.int与byte数组的互转

/***将32位的int值放到4字节的byte数组* @param num* @return*/public static byte[] intToByteArray(int num) { byte[] result = new byte[4]; result[0] = (byte)(num >>> 24);//取最高8位放到0下标 result[1] = (byte)(num >>> 16);//取次高8为放到1下标 result[2] = (byte)(num >>> 8); //取次低8位放到2下标 result[3] = (byte)(num ); //取最低8位放到3下标 return result;}/*** 将4字节的byte数组转成一个int值* @param b* @return*/public static int byteArrayToInt(byte[] b){ byte[] a = new byte[4]; int i = a.length - 1,j = b.length - 1; for (; i >= 0 ; i--,j--) {//从b的尾部(即int值的低位)开始copy数据 if(j >= 0) a[i] = b[j]; else a[i] = 0;//如果b.length不足4,则将高位补0 } int v0 = (a[0] & 0xff) << 24;//&0xff将byte值无差异转成int,避免Java自动类型提升后,会保留高位的符号位 int v1 = (a[1] & 0xff) << 16; int v2 = (a[2] & 0xff) << 8; int v3 = (a[3] & 0xff) ; return v0 + v1 + v2 + v3;}

3.long与byte数组的互转

/** * 将64位的long值放到8字节的byte数组 * @param num * @return 返回转换后的byte数组 */ public static byte[] longToByteArray(long num) { byte[] result = new byte[8]; result[0] = (byte) (num >>> 56);// 取最高8位放到0下标 result[1] = (byte) (num >>> 48);// 取最高8位放到0下标 result[2] = (byte) (num >>> 40);// 取最高8位放到0下标 result[3] = (byte) (num >>> 32);// 取最高8位放到0下标 result[4] = (byte) (num >>> 24);// 取最高8位放到0下标 result[5] = (byte) (num >>> 16);// 取次高8为放到1下标 result[6] = (byte) (num >>> 8); // 取次低8位放到2下标 result[7] = (byte) (num); // 取最低8位放到3下标 return result; } /** * 将8字节的byte数组转成一个long值 * @param byteArray * @return 转换后的long型数值 */ public static long byteArrayToInt(byte[] byteArray) { byte[] a = new byte[8]; int i = a.length - 1, j = byteArray.length - 1; for (; i >= 0; i--, j--) {// 从b的尾部(即int值的低位)开始copy数据 if (j >= 0) a[i] = byteArray[j]; else a[i] = 0;// 如果b.length不足4,则将高位补0 } // 注意此处和byte数组转换成int的区别在于,下面的转换中要将先将数组中的元素转换成long型再做移位操作, // 若直接做位移操作将得不到正确结果,因为Java默认操作数字时,若不加声明会将数字作为int型来对待,此处必须注意。 long v0 = (long) (a[0] & 0xff) << 56;// &0xff将byte值无差异转成int,避免Java自动类型提升后,会保留高位的符号位 long v1 = (long) (a[1] & 0xff) << 48; long v2 = (long) (a[2] & 0xff) << 40; long v3 = (long) (a[3] & 0xff) << 32; long v4 = (long) (a[4] & 0xff) << 24; long v5 = (long) (a[5] & 0xff) << 16; long v6 = (long) (a[6] & 0xff) << 8; long v7 = (long) (a[7] & 0xff); return v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7; }

4.float与byte数组的互转

/** * float转换byte * * @param bb * @param x * @param index */public static void putFloat(byte[] bb, float x, int index) { // byte[] b = new byte[4]; int l = Float.floatToIntBits(x); for (int i = 0; i < 4; i++) { bb[index + i] = new Integer(l).byteValue(); l = l >> 8; }}/** * 通过byte数组取得float * * @param bb * @param index * @return */public static float getFloat(byte[] b, int index) { int l; l = b[index + 0]; l &= 0xff; l |= ((long) b[index + 1] << 8); l &= 0xffff; l |= ((long) b[index + 2] << 16); l &= 0xffffff; l |= ((long) b[index + 3] << 24); return Float.intBitsToFloat(l);}

5.double与byte数组的互转

 /** * double转换byte * * @param bb * @param x * @param index */ public static void putDouble(byte[] bb, double x, int index) { // byte[] b = new byte[8]; long l = Double.doubleToLongBits(x); for (int i = 0; i < 4; i++) { bb[index + i] = new Long(l).byteValue(); l = l >> 8; } } /** * 通过byte数组取得float * * @param bb * @param index * @return */ public static double getDouble(byte[] b, int index) { long l; l = b[0]; l &= 0xff; l |= ((long) b[1] << 8); l &= 0xffff; l |= ((long) b[2] << 16); l &= 0xffffff; l |= ((long) b[3] << 24); l &= 0xffffffffl; l |= ((long) b[4] << 32); l &= 0xffffffffffl; l |= ((long) b[5] << 40); l &= 0xffffffffffffl; l |= ((long) b[6] << 48); l &= 0xffffffffffffffl; l |= ((long) b[7] << 56); return Double.longBitsToDouble(l); }

6、字符串和十六进制数的互转

写了一个工具类供大家参考:

package com.csc.stringtobyte;public class StringToByte{ public static void main(String[] args) { String string = new String("hello world!"); byte[] stringByte = string.getBytes(); String hexString = bytesToHexString(stringByte); System.out.println(hexString); byte[] binByte = hexStringToBytes(hexString); String result = new String(binByte); System.out.println(result); } /** * Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。 * @param src byte[] data * @return hex string */  public static String bytesToHexString(byte[] src){ StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * Convert hex string to byte[] * @param hexString the hex string * @return byte[] */ public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } /** * Convert char to byte * @param c char * @return byte */ private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); }}

7、将对象系列化成十六进制的字符串以及将十六机制的字符串反序列化成对象

写了一个工具类供大家参考:

package com.csc.util;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.Locale;public class SerializeTool { /** * 将传入的对象系列化后,存入参数string指定的文件,并将序列化后的对象转换成十六进制字符串返回 * @param object 可序列化的对象 * @param string 存储文件名 * @return string 序列化后的对象的十六进制字符串 * @throws FileNotFoundException * @throws IOException */ public static String writeObject(Object object, String strFile) throws FileNotFoundException, IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //用于将对象转换成byte[]数组的ObjectOutputStream ObjectOutputStream oos = new ObjectOutputStream(baos); //将对象写入ByteArrayOutputStream oos.writeObject(object); byte[] bytes = baos.toByteArray(); //用于将将对象存入文件的ObjectOutputStream ObjectOutputStream oos2 = new ObjectOutputStream(new FileOutputStream( strFile)); //将对象写入string指定的文件中 oos2.writeObject(object); oos.close(); oos2.close(); baos.close(); return bytesToHexString(bytes); } /** * 将序列化后且用十六进制字符表示的对象反序列化成对象 * @param hexString 序列化对象的十六进制表示形式的字符串 * @return 反序列化生成的对象 * @throws IOException * @throws ClassNotFoundException */ public static Object readObject(String hexString) throws IOException, ClassNotFoundException { byte[] bytes = hexStringToBytes(hexString); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } /** * 将传入的byte[]数组转换成十六机制数的字符串 * @param src 要转换的byte数组 * @return 返回十六进制的字符串 */ private static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; //将一个byte的二进制数转换成十六进制字符 String hv = Integer.toHexString(v); //如果二进制数转换成十六进制数高位为0,则加入'0'字符 if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * 将传进来的十六进制表示的字符串转换成byte数组 * @param hexString * @return 二进制表示的byte[]数组 */ private static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(Locale.getDefault()); int length = hexString.length() / 2; //将十六进制字符串转换成字符数组 char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { //一次去两个字符 int pos = i * 2; //两个字符一个对应byte的高四位一个对应第四位 d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } /** * 将传进来的字符代表的数字转换成二进制数 * @param c 要转换的字符 * @return 以byte的数据类型返回字符代表的数字的二进制表示形式 */ private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); }}
2f1d62cac16b03b6299ed4223e9047ec.gif
<think> 我们正在解决Java中long类型无法转换为java.math.BigDecimal的问题。根据引用,实际上我们通常是将BigDecimal转换long,但这里用户的需求是将long转换BigDecimal。实际上,在Java中,将long转换BigDecimal是非常直接的,因为BigDecimal有直接接受long的构造函数。 但是,用户提到“long类型无法转换为java.math.BigDecimal”,这可能是由于在某种上下文中出现了转换错误。根据引用[3][4],错误信息可能是“java.math.BigDecimal cannot be cast to java.lang.Long”,这实际上是相反的方向,即试图将BigDecimal对象强制转换Long类型,而这是不允许的。 因此,我们需要澄清: 1. 如果用户是想将long转换BigDecimal,那么直接使用构造函数:`new BigDecimal(long val)` 即可。 2. 如果用户遇到的是“java.math.BigDecimal cannot be cast to java.lang.Long”错误,那么问题在于试图将BigDecimal对象强制转换Long,而实际上应该使用BigDecimal转换方法(如`longValue()`)或者正确设计类型。 根据用户的问题描述,他想要的是将long转换BigDecimal的解决方案,所以我们应该提供第一种情况的方案。 然而,从引用[3][4]来看,用户可能是在其他上下文中(如MyBatis查询结果映射)遇到了类型转换问题。引用[4]提到了在MyBatis中出现的“java.math.BigDecimal cannot be cast to java.lang.Long”错误,这是因为数据库返回的数字类型(比如DECIMAL)被MyBatis映射成了BigDecimal,而用户代码试图将其强制转换Long。 因此,我们需要分两种情况来回答: 情况1:在纯Java代码中,如何将long转换BigDecimal? 情况2:在MyBatis等框架中,如何避免将BigDecimal错误地强制转换Long? 由于用户明确提到“long类型无法转换为java.math.BigDecimal”,我们重点解决情况1,但也需要考虑到用户可能实际上遇到了情况2(因为错误信息是相反的)。 步骤: 1. 首先说明在Java中如何正确地将long转换BigDecimal(使用构造函数)。 2. 然后解释如果用户遇到的是相反的异常(即BigDecimal无法Long),那么应该如何处理。 另外,根据引用[1][2],BigDecimallongValue()方法可以将BigDecimal转换long(截断小数部分),但这不是用户当前需要的。 所以,针对用户的问题,我们给出以下解答: 解答: 在Java中,将long类型转换BigDecimal非常简单,因为BigDecimal类提供了直接接受long类型参数的构造函数。例如: long myLong = 123456789L; BigDecimal myBigDecimal = new BigDecimal(myLong); 但是,如果您遇到的错误信息是“java.math.BigDecimal cannot be cast to java.lang.Long”,那么问题不是将longBigDecimal,而是将BigDecimal对象强制转换Long类型。这种情况通常发生在从数据库查询数据映射到Java对象时,数据库返回的是BigDecimal类型(例如,数据库中的DECIMAL类型),而您试图将其赋值给Long类型的变量。 解决这种错误的方法: 1. 使用BigDecimal转换方法:如果确定数值在long范围内,可以使用`longValue()`方法将BigDecimal转换long,然后再赋值给Long类型变量。但注意,如果BigDecimal的值超过了long的范围,会丢失高位数(只取低64位)。 2. 在SQL查询中使用类型转换:在MyBatis中,可以在SQL语句中使用CAST或CONVERT函数将数据库字段转换为有符号整数(SIGNED),这样MyBatis就会将其映射为Long类型。例如: SELECT CAST(column_name AS SIGNED) FROM table_name; 3. 在MyBatis的映射文件中,使用resultType为Long,并确保SQL返回的是整数类型,或者使用类型处理器(TypeHandler)来处理转换。 总结: - 将long转换BigDecimal:使用`new BigDecimal(long)`。 - 解决BigDecimal无法强制转换Long:不要强制转换,而是通过方法转换(如`longValue()`)或SQL层转换。 如果用户是在MyBatis中遇到问题,可以参考引用[4]中的类型转换方法。 相关问题: 1. 如何将BigDecimal转换long? 2. 在MyBatis中如何处理数据库的DECIMAL类型到Java Long的映射? 3. 使用BigDecimal的构造函数时需要注意什么? </think> ### Java中long类型转换BigDecimal的解决方案 在Java中,long类型无法直接转换BigDecimal的问题通常是由于类型处理不当引起的。以下是完整的解决方案: #### 1. **正确转换方法** 使用`BigDecimal`的构造函数即可实现转换: ```java long longValue = 123456789L; BigDecimal bigDecimal = new BigDecimal(longValue); // 正确转换方法 ``` - ✅ **说明**:`BigDecimal`提供了直接接收`long`类型参数的构造函数,无需额外处理[^1][^2]。 #### 2. **常见错误场景与修复** **错误示例**: ```java Object obj = new BigDecimal(100); Long value = (Long) obj; // 抛出 ClassCastException ``` **错误原因**:试图将`BigDecimal`对象强制转换为`Long`类型(而非`long`基本类型)。 **修复方案**: ```java // 正确方式:使用 longValue() 方法 BigDecimal bigDecimal = new BigDecimal(100); long primitiveLong = bigDecimal.longValue(); // 转换为基本类型 Long wrapperLong = bigDecimal.longValue(); // 自动装箱为包装类 ``` #### 3. **框架中的特殊处理(如MyBatis)** 在MyBatis等ORM框架中,需确保类型匹配: ```xml <!-- Mapper XML 示例 --> <select id="getValue" resultType="java.lang.Long"> SELECT CAST(decimal_column AS SIGNED) FROM table <!-- SQL层转换 --> </select> ``` - 使用`CAST(column AS SIGNED)`将数据库的`DECIMAL`类型为有符号整数[^4]。 #### 4. **注意事项** - **精度问题**:`longValue()`会丢弃小数部分(如 `123.45` → `123`)[^1]。 - **范围溢出**:若`BigDecimal`值超过`Long.MAX_VALUE`($2^{63}-1$),结果将截断为低64位。 - **空值处理**:转换前需检查`BigDecimal`是否为`null`,避免`NullPointerException`[^3]。 ### 总结步骤 1. **基础转换** → 用构造函数 `new BigDecimal(long)` 2. **反向转换** → 用 `longValue()` 而非强制类型转换 3. **数据库处理** → 在SQL层使用 `CAST` 或类型处理器 4. **异常防护** → 检查空值并处理溢出 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值