Java【基础版本】SerializationUtils#Clone浅拷贝、深拷贝

引入:今天工作中同事使用了Java8 Lists.partition 函数来批量更新/查询数据,架构组在mybatis插件扩展了mybatis#Interceptor 方法,具体实现拦截网上有大量资料可以查询下,这里就不引入介绍,连接器中使用 SerializationUtils.clone((Serializable) originParameter); 方法,来序列号param 对象,在对象复制的时候Lists.partition后得到的list 是一个Partition对象,该对象是继承了AbstractList 完成list 切分的。

我们看下Lists.partition源码:

 public static <T> List<List<T>> partition(List<T> list, int size) {
        Preconditions.checkNotNull(list);
        Preconditions.checkArgument(size > 0);
        return (List)(list instanceof RandomAccess ? new Lists.RandomAccessPartition(list, size) : new Lists.Partition(list, size));
    }
 private static class Partition<T> extends AbstractList<List<T>> {
        final List<T> list;
        final int size;

        Partition(List<T> list, int size) {
            this.list = list;
            this.size = size;
        }

        public List<T> get(int index) {
            Preconditions.checkElementIndex(index, this.size());
            int start = index * this.size;
            int end = Math.min(start + this.size, this.list.size());
            return this.list.subList(start, end);
        }

        public int size() {
            return IntMath.divide(this.list.size(), this.size, RoundingMode.CEILING);
        }

        public boolean isEmpty() {
            return this.list.isEmpty();
        }
    }

看下对象Partition list对象属于内部类,没实现implements Serializable接口导致序列号失败
错误提示:

Caused by: org.apache.commons.lang3.SerializationException: java.io.NotSerializableException: java.util.ArrayList$SubList
	at org.apache.commons.lang3.SerializationUtils.serialize(SerializationUtils.java:273) ~[commons-lang3-3.12.0.jar:3.12.0]
	at org.apache.commons.lang3.SerializationUtils.serialize(SerializationUtils.java:248) ~[commons-lang3-3.12.0.jar:3.12.0]
	at org.apache.commons.lang3.SerializationUtils.clone(SerializationUtils.java:138) ~[commons-lang3-3.12.0.jar:3.12.0]
	at com.txxy.cloud.starter.druid.interceptor.CipherInterceptor.intercept(CipherInterceptor.java:92) ~[txxy-cloud-starter-druid-1.8.0-SNAPSHOT.jar:1.8.0-SNAPSHOT]
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) ~[mybatis-3.5.5.jar:3.5.5]
	at com.sun.proxy.$Proxy466.update(Unknown Source) ~[?:?]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) ~[mybatis-3.5.5.jar:3.5.5]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:184) ~[mybatis-3.5.5.jar:3.5.5]
	at sun.reflect.GeneratedMethodAccessor1471.invoke(Unknown Source) ~[?:?]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_212]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_212]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ~[mybatis-spring-2.0.5.jar:2.0.5]

正文:

浅复制

浅层复制: 被复制的对象的所有成员属性都有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

换言之,浅层复制仅仅复制所考虑的对象(对象属性、数据),而不复制它所引用的对象(对象地址)。

深复制

深层复制:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不是原有的那些被引用的对象。

换言之,深层复制要复制的对象引用的对象(对象属性、数据)都复制一遍。

2.深拷贝实现起来也比较简单,只需要对对象中的对象再次进行clone操作:

commons-lang-2.6.jar

例如:Object obj = SerializationUtils.clone( objectFrom )

源码:

   /**
     * 

Deep clone an {@code Object} using serialization.

* *

This is many times slower than writing clone methods by hand * on all objects in your object graph. However, for complex object * graphs, or for those that don't support deep cloning this can * be a simple alternative implementation. Of course all the objects * must be {@code Serializable}.

* * @param the type of the object involved * @param object the {@code Serializable} object to clone * @return the cloned object * @throws SerializationException (runtime) if the serialization fails */
public static <T extends Serializable> T clone(final T object) { if (object == null) { return null; } final byte[] objectData = serialize(object); final ByteArrayInputStream bais = new ByteArrayInputStream(objectData); try (ClassLoaderAwareObjectInputStream in = new ClassLoaderAwareObjectInputStream(bais, object.getClass().getClassLoader())) { /* * when we serialize and deserialize an object, * it is reasonable to assume the deserialized object * is of the same type as the original serialized object */ @SuppressWarnings("unchecked") // see above final T readObject = (T) in.readObject(); return readObject; } catch (final ClassNotFoundException ex) { throw new SerializationException("ClassNotFoundException while reading cloned object data", ex); } catch (final IOException ex) { throw new SerializationException("IOException while reading or closing cloned object data", ex); } }

笔记就介绍这里了~~

你可能感兴趣的:(java,java,mybatis,开发语言)