一、为什么需要将object转化为byte数组
在数据的传输和存储过程中,我们常常需要将对象转化为byte数组。这主要是因为在网络传输、磁盘存储、对象序列化等场景中,byte数组具有以下几个优点:
1、在各种机器和系统之间传输数据的唯一通用方式就是将数据转换成byte数组
2、byte数组在JAVA和.NET等主流编程语言中被广泛的使用
3、更加灵活处理数据
示例代码:
public static byte[] objectToByteArray(Object obj) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(out); os.writeObject(obj); return out.toByteArray(); }
二、如何实现object转byte数组
实现将object转化为byte数组的方法基本上分为两个方案:
1、使用Java序列化机制,将目标对象序列化为byte数组
2、手工编写二进制转换工具类,将目标对象按照特定的顺序转换为byte数组
使用第一个方案的好处是,无需考虑数据存储结构和数据类型,因为Java序列化机制会自动处理这些问题。
另一方面,由于Java序列化机制是重量级的,一些对象序列化时会存在性能问题,例如大量的计算和IO连续读写。
示例代码:
public static byte[] serialize(Object obj) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(obj); return bos.toByteArray(); }
三、如何反序列化byte数组为object
如果要将byte数组转换回对象,必须将byte数组还原为原始的Java对象。
示例代码:
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); }
四、如何处理非序列化对象
在某些情况下,对象可能无法进行Java序列化,此时可以使用手工编写的转换工具类将对象转换为byte数组。
示例代码:
public static byte[] toByteArray(String s) { try { byte[] data = s.getBytes("ISO-8859-1"); int len = data.length; byte[] out = new byte[len]; for (int i = 0; i < len; i++) { out[i] = data[i]; } return out; } catch (UnsupportedEncodingException e) { return null; } }
五、如何处理序列化对象中的特殊情况
在某些情况下,序列化对象可能会遇到一些特殊情况,例如:
1、序列化的对象含有敏感信息,需要忽略这部分信息
2、序列化时出现循环应用,需要正常转换
示例代码:
public class CustomObjectOutputStream extends ObjectOutputStream { public CustomObjectOutputStream(OutputStream out) throws IOException { super(out); } @Override protected void writeStreamHeader() throws IOException { return; } @Override protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { return; } }
六、遇到byte数组转object卡顿咋办
当byte数组非常大时,将byte数组转化为object可能会非常耗时。
一种简单的解决方法是,将byte数组分割成多个部分,然后逐步转换为不同的object。
示例代码:
public static List<Object> splitArray(Object[] array, int chunkSize) { List<Object> listOfArrays = new ArrayList<Object>(); int totalSize = array.length; int offset = 0; while (totalSize > 0) { int length = Math.min(totalSize, chunkSize); Object subArray = Array.newInstance(array.getClass().getComponentType(), length); System.arraycopy(array, offset, subArray, 0, length); offset += length; totalSize -= length; listOfArrays.add(subArray); } return listOfArrays; }
七、如何进行序列化和反序列化的性能测试
如何进行Java序列化和反序列化的性能测试?目前最常用的是使用jmh测试框架:JMH 是用于基准测试的 Java Microbenchmark Harness,是 OpenJDK 工具集的一部分,提供了简单而强大的基准测试方法。它的使用方式类似JUnit,基于注解构建并运行测试。
示例代码:
@BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) @Fork(value = 1, jvmArgs = {"-Xms2G", "-Xmx2G"}) @Warmup(iterations = 3) @Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) public class SerializationTest { private static final byte[] DATA = createData(); private static final Serializable OBJECT = new MyObject(); private static byte[] createData() { Random random = new Random(); byte[] data = new byte[1024 * 1024]; random.nextBytes(data); return data; } @Benchmark public byte[] serialize() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(OBJECT); return bos.toByteArray(); } @Benchmark public Object deserialize() throws IOException, ClassNotFoundException { ByteArrayInputStream bis = new ByteArrayInputStream(serialize()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } }