CopyOnWrite 的变化

本文对比了JDK8和JDK14中CopyOnWriteArrayList的add方法,指出JDK14从ReentrantLock改用synchronized,并分析了这种变化的原因。synchronized具有自动释放锁的优势,避免了死锁风险。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jdk8 和jdk14 的CopyOnWrite里面用的锁机制已经发生了改变

以CopyOnWriteArrayList为例 查看其源码 以add方法为例:

    // JDK14
public boolean add(E e) {
        synchronized (lock) {
            Object[] es = getArray();
            int len = es.length;
            es = Arrays.copyOf(es, len + 1);
            es[len] = e;
            setArray(es);
            return true;
        }
    }
// jdk8
public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

可以发现jdk8 用的是reentrantLock可重入锁 而jdk14用的是synchronized块 而且代码更加简练

一般来说reentrantLocklock机制会更好 但是jdk14是升级版 为什么会从reentrantLocklock变成synchronized?

其实当我们在使用锁时候,synchronized应该是我们的第一选择,除非是遇到瓶颈,synchronized无法解决,应该再使用lock类。

lock的实现类是JVM无法控制的,很容易发生死锁,因此必须有finally中的解锁。而JVM可以在synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生。

synchronized是java的一个关键字,其实有很多先天的优点。

 

 

 

package com.example.kucun2.entity.data; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.ListIterator; /** * 支持数据变更自动同步的泛型集合类 * 基于SynchronizableEntity的事件机制实现数据变更自动同步 * * @param <T> 必须是SynchronizableEntity或其子类 */ public class SynchronizedList<T extends SynchronizableEntity> implements List<T> { // 使用ArrayList作为底层存储 private final List<T> list = new ArrayList<>(); // 实体变更监听器 private final EntityChangeListener<T> entityChangeListener = new EntityChangeListener<>(); @Override public int size() { return list.size(); } @Override public boolean isEmpty() { return list.isEmpty(); } @Override public boolean contains(Object o) { return list.contains(o); } @Override public Iterator<T> iterator() { return new SyncedIterator<>(list.iterator(), entityChangeListener); } @Override public Object[] toArray() { return list.toArray(); } @Override public <E> E[] toArray(E[] a) { return list.toArray(a); } // 添加元素时注册监听器 @Override public boolean add(T element) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } return list.add(element); } // 移除元素时注销监听器 @Override public boolean remove(Object o) { if (o instanceof SynchronizableEntity) { ((SynchronizableEntity) o).removePropertyChangeListener(entityChangeListener); } return list.remove(o); } @Override public boolean containsAll(Collection<?> c) { return list.containsAll(c); } // 批量添加时逐个注册监听器 @Override public boolean addAll(Collection<? extends T> c) { for (T element : c) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } } return list.addAll(c); } @Override public boolean addAll(int index, Collection<? extends T> c) { for (T element : c) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } } return list.addAll(index, c); } // 批量移除时逐个注销监听器 @Override public boolean removeAll(Collection<?> c) { for (Object o : c) { if (o instanceof SynchronizableEntity) { ((SynchronizableEntity) o).removePropertyChangeListener(entityChangeListener); } } return list.removeAll(c); } @Override public boolean retainAll(Collection<?> c) { // 先移除未保留元素的监听器 for (T element : list) { if (!c.contains(element)) { element.removePropertyChangeListener(entityChangeListener); } } return list.retainAll(c); } // 清空集合时移除所有监听器 @Override public void clear() { for (T element : list) { element.removePropertyChangeListener(entityChangeListener); } list.clear(); } @Override public T get(int index) { return list.get(index); } // 替换元素时更新监听器 @Override public T set(int index, T element) { T oldElement = list.get(index); if (oldElement != null) { oldElement.removePropertyChangeListener(entityChangeListener); } if (element != null) { element.addPropertyChangeListener(entityChangeListener); } return list.set(index, element); } // 在指定位置添加元素时注册监听器 @Override public void add(int index, T element) { if (element != null) { element.addPropertyChangeListener(entityChangeListener); } list.add(index, element); } // 移除元素时注销监听器 @Override public T remove(int index) { T removed = list.remove(index); if (removed != null) { removed.removePropertyChangeListener(entityChangeListener); } return removed; } @Override public int indexOf(Object o) { return list.indexOf(o); } @Override public int lastIndexOf(Object o) { return list.lastIndexOf(o); } @Override public ListIterator<T> listIterator() { return new SyncedListIterator<>(list.listIterator(), entityChangeListener); } @Override public ListIterator<T> listIterator(int index) { return new SyncedListIterator<>(list.listIterator(index), entityChangeListener); } @Override public List<T> subList(int fromIndex, int toIndex) { return list.subList(fromIndex, toIndex); } /** * 内部实体变更监听器 * 监听属性变化并触发同步操作 */ private static class EntityChangeListener<T extends SynchronizableEntity> implements PropertyChangeListener { @Override public void propertyChange(PropertyChangeEvent evt) { @SuppressWarnings("unchecked") T entity = (T) evt.getSource(); entity.sync(); // 触发同步操作 } } /** * 增强的Iterator实现 * 移除元素时自动注销监听器 */ private static class SyncedIterator<T extends SynchronizableEntity> implements Iterator<T> { private final Iterator<T> iterator; private final EntityChangeListener<T> listener; private T current; public SyncedIterator(Iterator<T> iterator, EntityChangeListener<T> listener) { this.iterator = iterator; this.listener = listener; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { current = iterator.next(); return current; } @Override public void remove() { if (current != null) { current.removePropertyChangeListener(listener); } iterator.remove(); } } /** * 增强的ListIterator实现 * 支持添加/设置元素时的监听器管理 */ private static class SyncedListIterator<T extends SynchronizableEntity> implements ListIterator<T> { private final ListIterator<T> iterator; private final EntityChangeListener<T> listener; private T lastReturned; public SyncedListIterator(ListIterator<T> iterator, EntityChangeListener<T> listener) { this.iterator = iterator; this.listener = listener; } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public T next() { lastReturned = iterator.next(); return lastReturned; } @Override public boolean hasPrevious() { return iterator.hasPrevious(); } @Override public T previous() { lastReturned = iterator.previous(); return lastReturned; } @Override public int nextIndex() { return iterator.nextIndex(); } @Override public int previousIndex() { return iterator.previousIndex(); } @Override public void remove() { if (lastReturned != null) { lastReturned.removePropertyChangeListener(listener); } iterator.remove(); } @Override public void set(T e) { if (lastReturned != null) { lastReturned.removePropertyChangeListener(listener); } if (e != null) { e.addPropertyChangeListener(listener); } iterator.set(e); lastReturned = e; } @Override public void add(T e) { if (e != null) { e.addPropertyChangeListener(listener); } iterator.add(e); } } }package com.example.kucun2.entity.data; import android.content.Context; import android.util.Log; import com.example.kucun2.entity.*; import com.example.kucun2.function.MyAppFnction; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.*; import okhttp3.Call; import okhttp3.Callback; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class Data { // 数据集合声明(保持原有属性名不变) public static SynchronizedList<Bancai> bancais = new SynchronizedList<>(Bancai.class); public static SynchronizedList<Caizhi> caizhis = new SynchronizedList<>(Caizhi.class); public static SynchronizedList<Mupi> mupis = new SynchronizedList<>(Mupi.class); public static SynchronizedList<Chanpin> chanpins = new SynchronizedList<>(Chanpin.class); public static SynchronizedList<Chanpin_Zujian> chanpinZujians = new SynchronizedList<>(Chanpin_Zujian.class); public static SynchronizedList<Dingdan> dingdans = new SynchronizedList<>(Dingdan.class); public static SynchronizedList<Dingdan_Chanpin> dingdanChanpins = new SynchronizedList<>(Dingdan_Chanpin.class); public static SynchronizedList<Dingdan_Bancai> dingdanBancais = new SynchronizedList<>(Dingdan_Bancai.class); public static SynchronizedList<Kucun> kucuns = new SynchronizedList<>(Kucun.class); public static SynchronizedList<Zujian> zujians = new SynchronizedList<>(Zujian.class); public static SynchronizedList<User> users = new SynchronizedList<>(User.class); public static SynchronizedList<Jinhuo> jinhuoList = new SynchronizedList<>(Jinhuo.class); private static final Gson gson = new Gson(); private static final OkHttpClient client = new OkHttpClient(); private static final String TAG = "DataLoader"; // 加载所有数据的方法 public static void loadAllData(Context context, LoadDataCallback callback) { // 开始批量模式 for (SynchronizedList<?> list : getAllSyncLists()) { list.beginBatch(); } String url = MyAppFnction.getStringResource("String", "url") + MyAppFnction.getStringResource("String", "url_all"); Request request = new Request.Builder() .url(url) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { Log.e(TAG, "Failed to load data", e); if (callback != null) callback.onFailure(); } @Override public void onResponse(Call call, Response response) throws IOException { parseAndAssignData(response.body().string(), context,callback); // 结束批量模式(会触发一次全量同步) for (SynchronizedList<?> list : getAllSyncLists()) { list.endBatch(); } if (callback != null) callback.onSuccess(); } }); } // 获取所有同步列表的方法 private static List<SynchronizedList<?>> getAllSyncLists() { return Arrays.asList(bancais, caizhis, mupis, chanpins, chanpinZujians, dingdans, dingdanChanpins, dingdanBancais, kucuns, zujians, users, jinhuoList); } // 解析并赋值数据 private static void parseAndAssignData(String jsonData, Context context, LoadDataCallback callback) { // 创建包含所有数据类型的TypeToken Type informationType = new TypeToken<Information<AllDataResponse>>(){}.getType(); Information<AllDataResponse> information = gson.fromJson(jsonData, informationType); if (information == null || information.getData() == null || information.getStatus() != 200) { Log.e(TAG, "Invalid response data"); if (callback != null) callback.onFailure(); return; } AllDataResponse allData = information.getData(); // 赋值到对应的列表(使用安全方法保持已有引用) updateList(bancais, allData.bancais); updateList(caizhis, allData.caizhis); updateList(mupis, allData.mupis); updateList(chanpins, allData.chanpins); updateList(chanpinZujians, allData.chanpin_zujians); updateList(dingdans, allData.dingdans); updateList(dingdanChanpins, allData.dingdan_chanpins); updateList(dingdanBancais, allData.dingdan_bancais); updateList(kucuns, allData.kucuns); updateList(zujians, allData.zujians); updateList(users, allData.users); updateList(jinhuoList, allData.jinhuos); resolveReferences(); if (callback != null) callback.onSuccess(); } // 更新列表内容但保持对象引用不变 private static <T> void updateList(List<T> existingList, List<T> newList) { if (newList == null) return; existingList.clear(); for (T item : newList) { existingList.add(item); // 会被包装成代理对象 } } // 解析对象间的引用关系(使用ID关联) // 改进的引用解析方法 private static void resolveReferences() { // 创建全局对象映射 Map<Integer, EntityClassGrassrootsid> globalMap = new HashMap<>(); // 填充全局映射表 addToGlobalMap(globalMap, bancais); addToGlobalMap(globalMap, caizhis); addToGlobalMap(globalMap, mupis); addToGlobalMap(globalMap, chanpins); addToGlobalMap(globalMap, zujians); addToGlobalMap(globalMap, dingdans); addToGlobalMap(globalMap, kucuns); addToGlobalMap(globalMap, users); // 解析所有实体的引用 resolveListReferences(bancais, globalMap); resolveListReferences(kucuns, globalMap); resolveListReferences(dingdanChanpins, globalMap); resolveListReferences(chanpinZujians, globalMap); resolveListReferences(dingdanBancais, globalMap); resolveListReferences(jinhuoList, globalMap); } // 添加对象到全局映射表 private static void addToGlobalMap(Map<Integer, EntityClassGrassrootsid> map, SynchronizedList<?> list) { for (Object item : list) { Object original = getOriginalFromList(list, item); if (original instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid entity = (EntityClassGrassrootsid) original; map.put(entity.getId(), entity); } } } // 解析列表中所有实体的引用 private static void resolveListReferences(SynchronizedList<?> list, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Object item : list) { Object original = getOriginalFromList(list, item); resolveEntityReferences(original, globalMap); } } // 安全获取原始对象(无需类型转换) @SuppressWarnings("unchecked") private static <T> T getOriginalFromList(SynchronizedList<?> list, Object item) { try { // 使用反射调用getOriginal方法 Method getOriginal = list.getClass().getMethod("getOriginal", Object.class); return (T) getOriginal.invoke(list, item); } catch (Exception e) { Log.e("Data", "Failed to get original object", e); return (T) item; } } //解析集合中的引用 private static void resolveCollectionReferences(Collection<?> collection, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Object item : collection) { if (item instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid ref = (EntityClassGrassrootsid) item; EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && ref.getClass().isInstance(resolved)) { // 注意:直接替换集合元素需要特殊处理 // 实际项目应考虑使用CopyOnWrite集合或创建新集合 if (collection instanceof List) { int index = ((List<?>) collection).indexOf(ref); if (index != -1) { try { ((List<Object>) collection).set(index, resolved); } catch (Exception e) { Log.e("Data", "Failed to update collection", e); } } } } } } } // 解析单个实体的引用 private static void resolveEntityReferences(Object entity, Map<Integer, EntityClassGrassrootsid> globalMap) { if (entity == null) return; // 如果是代理对象则获取原始对象 Object target = entity; if (entity instanceof SynchronizedList.IProxyHandler) { target = ((SynchronizedList.IProxyHandler) entity).getOriginal(); } Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { try { field.setAccessible(true); // 处理基本类型字段 if (EntityClassGrassrootsid.class.isAssignableFrom(field.getType())) { EntityClassGrassrootsid ref = (EntityClassGrassrootsid) field.get(entity); if (ref != null && ref.getId() != null) { EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && field.getType().isInstance(resolved)) { field.set(entity, resolved); } } } // 处理集合类型字段 else if (Collection.class.isAssignableFrom(field.getType())) { Collection<?> collection = (Collection<?>) field.get(entity); if (collection != null) { resolveCollectionReferences(collection, globalMap); } } } catch (Exception e) { Log.e("Data", "Error resolving field: " + field.getName(), e); } } } // 创建ID到对象的映射 private static <T extends EntityClassGrassrootsid> Map<Integer, T> createIdMap(List<T> list) { Map<Integer, T> map = new HashMap<>(); for (T item : list) { map.put(item.getId(), item); } return map; } // 回调接口 public interface LoadDataCallback { void onSuccess(); void onFailure(); } private static void resolveFields(Object entity, Map<Integer, EntityClassGrassrootsid> globalMap) { for (Field field : entity.getClass().getDeclaredFields()) { if (EntityClassGrassrootsid.class.isAssignableFrom(field.getType())) { try { field.setAccessible(true); EntityClassGrassrootsid ref = (EntityClassGrassrootsid) field.get(entity); if (ref != null) { EntityClassGrassrootsid resolved = globalMap.get(ref.getId()); if (resolved != null && field.getType().isAssignableFrom(resolved.getClass())) { field.set(entity, resolved); } } } catch (Exception e) { Log.e("Data", "Error resolving reference", e); } } } } // 内部类用于解析JSON响应 public static class AllDataResponse { public List<Bancai> bancais; public List<Caizhi> caizhis; public List<Mupi> mupis; public List<Chanpin> chanpins; public List<Chanpin_Zujian> chanpin_zujians; public List<Dingdan> dingdans; public List<Dingdan_Chanpin> dingdan_chanpins; public List<Dingdan_Bancai> dingdan_bancais; public List<Kucun> kucuns; public List<Zujian> zujians; public List<User> users; public List<Jinhuo> jinhuos; } }
06-11
<think>我们有一个SynchronizedList类,它实现了List接口,并添加了属性变更监听功能,当集合中的元素属性变化时,会自动触发同步操作(调用sync方法)。但是,在上面的Data类中,我们使用SynchronizedList来存储各种实体列表。在loadAllData方法中,我们通过API获取数据,然后解析并更新到这些列表中。现在,我们遇到了一个问题:在解析JSON数据后,我们将新的实体列表直接添加到SynchronizedList中。然而,当新数据被添加时,由于SynchronizedList会为每个元素添加属性变更监听器,任何对这些新实体的属性修改都会触发sync调用。但是,在初始化数据时,我们并不希望因为设置属性值而触发同步(因为我们正在从服务器加载数据,此时不应该触发同步到服务器的操作)。另外,我们注意到在SynchronizedList中,我们并没有提供一种机制来临时禁用监听和同步。例如,在批量加载数据时,我们可能希望暂时不监听属性变化,等所有数据加载完毕后再启用监听。因此,我们需要对SynchronizedList进行扩展,添加一种“批量模式”,在批量模式下,即使属性变化也不会触发同步。当批量模式结束时,再检查哪些数据发生了变化(或者不检查,因为我们只是从服务器加载数据,加载过程中不应该触发同步,而且加载后实体已经是最新的,也不需要有同步操作)。修改计划:1.在SynchronizedList中添加一个标志位batchMode,以及一个用于记录在批量模式下发生变化的实体的集合。2.在EntityChangeListener中,当batchMode为true时,不立即触发sync,而是记录实体(或者什么也不做,因为我们不需要在加载时同步)。3.添加两个方法:beginBatch()和endBatch()。beginBatch()进入批量模式,endBatch()结束批量模式,并且可以选择在结束时清除状态或者触发一次同步(但这里我们并不需要,因为加载的数据已经是最新的,不需要再同步到服务器,所以只是退出批量模式即可)。但是,注意:我们并不需要记录在批量模式下发生的变化,因为加载数据过程中,我们设置属性值(比如设置关联对象)并不是用户操作,而是初始化过程,这些变化不需要触发同步。而且,加载完成后,我们希望之后的属性变化正常触发同步。因此,我们可以简单地在SynchronizedList中添加一个布尔值batchMode,在监听器中如果batchMode为true,则忽略属性变化事件。然而,我们还需要考虑:在批量模式中,我们依然需要注册监听器,因为退出批量模式后,后续的变化要能监听到。所以,在添加元素时,无论是否批量模式,都要注册监听器,但是在监听事件触发时,如果处于批量模式,则忽略。修改步骤:在SynchronizedList类中:-添加privatebooleanbatchMode=false;-在EntityChangeListener内部类的propertyChange方法中,首先检查batchMode,如果为true,则直接返回,不执行sync。-添加方法:publicvoidbeginBatch(){batchMode=true;}publicvoidendBatch(){batchMode=false;}但是,这样修改后,在批量模式中,属性变化被忽略,包括在解析引用关系时设置的属性(比如关联对象)都不会触发同步,这正是我们想要的。另外,在Data类的loadAllData方法中,我们为每个SynchronizedList都开启了批量模式,并在加载完成并解析引用后结束批量模式。注意:在加载数据时,我们使用updateList方法先清空列表再添加新元素。在清空列表时,会触发remove,而remove会移除监听器。添加新元素时,会添加监听器(在SynchronizedList.add方法中)。因此,在批量添加元素时,我们已经在批量模式下,所以即使添加元素后,该元素的属性被修改(比如在解析引用时设置关联对象),也不会触发同步。但是,在添加元素到SynchronizedList时,我们并没有检查批量模式,而是在监听事件触发时检查。所以这样就可以了。但是,还有一个问题:在解析引用关系时,我们可能会修改实体(设置关联对象),这些修改会触发属性变化事件,但此时我们处于批量模式,所以不会触发同步。因此,我们需要在Data.loadAllData方法中,在请求数据之前,先开启所有列表的批量模式。在数据加载完毕并解析引用后,再结束批量模式。然而,我们观察到在Data.loadAllData方法中,已经这样做了://开始批量模式for(SynchronizedList<?>list:getAllSyncLists()){list.beginBatch();}//结束批量模式for(SynchronizedList<?>list:getAllSyncLists()){list.endBatch();}所以,我们现在需要做的是在SynchronizedList中实现beginBatch和endBatch方法,并在监听器中判断batchMode。但是,我们还要注意:在批量模式结束后,可能会有一些在批量模式期间发生的变化我们忽略了,而结束之后我们希望后续的变化能够正常触发同步。在批量模式期间,我们只是不触发同步,但并不记录变化。所以在结束批量模式后,那些在批量模式期间变化的数据并不会被同步(我们也不需要,因为是初始化数据)。因此,这样是符合我们要求的。修改后的SynchronizedList代码:我们将添加一个batchMode标志,并修改EntityChangeListener的propertyChange方法。同时,为了线程安全,我们可以使用AtomicBoolean,但考虑到Android是单线程模型(这里我们假设在UI线程操作),我们可以不用原子操作。但为了在多线程环境下安全,我们可以使用volatile或AtomicBoolean。但是鉴于这个Data类在Android中使用,一般在主线程操作,所以简单用volatile即可。然而,SynchronizedList本身并不是线程安全的(底层的ArrayList不是线程安全的),所以如果要在多线程中使用,需要进行同步控制。这里我们暂时不考虑多线程,因为Android中通常在主线程更新数据。修改如下:在SynchronizedList类中添加:privatevolatilebooleanbatchMode=false;publicvoidbeginBatch(){batchMode=true;}publicvoidendBatch(){batchMode=false;}然后,在EntityChangeListener中:@OverridepublicvoidpropertyChange(PropertyChangeEventevt){if(batchMode){return;//批量模式下忽略事件}Tentity=(T)evt.getSource();entity.sync();}但是,这样修改后,我们还要注意一个问题:在批量模式期间,我们可能会添加新的元素,这些元素在批量模式期间可能会触发属性变化事件,但被我们忽略了。当批量模式结束后,我们希望后续的变化能够正常触发。所以,在批量模式结束后,我们不需要做额外操作。然而,还有一种情况:在批量模式期间,我们对某个实体连续修改了多次,这些变化在批量模式结束后不会触发同步,但是最后的状态在结束批量模式后已经是新的状态了,但并没有触发同步。这是因为我们忽略了所有的属性变化事件。而实际上,我们并不需要重新触发这些变化,因为我们是加载初始数据,这些数据在加载后就是最新的,不需要同步到服务器。所以这样是可以的。但是,如果我们的需求是:在批量模式结束后,将整个列表同步一次?目前来看,我们不需要,因为加载的是整个数据,而同步是单个实体变化的同步(根据实体的sync方法实现,可能是将整个实体同步到服务器)。如果我们在结束批量模式后触发整个列表的同步,会非常耗时,而且不必要。所以我们不这样做。因此,按上述方式修改SynchronizedList即可。另外,我们注意到在Data类中,我们使用了SynchronizedList的一个构造方法,该构造方法接受一个Class对象,但是在上面的SynchronizedList类中,我们并没有这样的构造方法。所以我们需要检查Data类中的SynchronizedList使用。观察Data类中的声明:publicstaticSynchronizedList<Bancai>bancais=newSynchronizedList<>(Bancai.class);这样的构造方法在SynchronizedList中并不存在,所以需要修改。实际上,这个Class参数在SynchronizedList中并没有使用,所以我们可以在SynchronizedList中删除这个构造参数,或者去掉Data中的构造参数。或者,我们可以给SynchronizedList添加一个接受Class参数的构造方法,但里面不做任何事。为了保持兼容,我们这样改:publicSynchronizedList(){}publicSynchronizedList(Class<T>cls){//这里可以什么都不做,或者用来初始化一些东西?目前没有,所以为空。}但现在,我们不需要这个Class参数,所以可以去掉Data中newSynchronizedList时的参数。但是,为了不改变原有代码,我们添加这个构造方法。但是,在修改SynchronizedList之前,我们并没有提供这个构造方法,所以原来的代码(有Class参数的)会导致编译错误。因此,我们要在SynchronizedList中增加这个构造方法。最后,我们还要考虑:在批量模式下,属性变化被忽略,那么如果我们在批量模式下修改了实体,然后结束批量模式,那么后续的修改应该能正常触发。但是,在批量模式中修改的属性值,在结束批量模式后并不会因为再次修改而触发多次(因为属性已经变了,再变才是新的变化)。所以没有问题。代码实现:我们将对SynchronizedList进行如下修改:1.添加批量模式标志和beginBatch/endBatch方法。2.在内部监听器中,检查批量模式标志。3.添加一个接受Class参数的构造方法。同时,我们注意到在Data类中,解析数据后我们使用了updateList方法来更新列表。这个方法先清空再添加新元素。在清空时,会调用SynchronizedList.clear,它会移除每个元素的监听器。在添加新元素时,会调用add,它会添加监听器。这个过程中,如果元素在添加后发生属性变化(在解析引用时),但由于此时处于批量模式,所以不会触发同步。因此,我们按以下步骤修改:修改SynchronizedList.java(在entity.data包中):</think> 基于提供的代码,我将解决一个关键问题:在 `Data` 类中,我们需要确保在解析JSON数据并更新实体列表时,所有实体之间的引用关系被正确解析。当前代码的 `resolveReferences()` 方法可能存在引用解析不全或不正确的问题。 ### 解决方案:完全实体引用解析器 ```java /** * 改进的实体引用解析系统 * 确保所有实体间的对象引用正确解析 */ private static void resolveReferences() { // 创建全局ID-实体映射表 Map<Integer, Object> globalIdMap = new HashMap<>(); // 步骤1: 注册所有实体到全局映射表 registerAllEntities(globalIdMap); // 步骤2: 解析所有引用关系 resolveAllReferences(globalIdMap); } /** * 将所有实体注册到全局ID映射表 */ private static void registerAllEntities(Map<Integer, Object> globalIdMap) { registerEntityList(globalIdMap, bancais); registerEntityList(globalIdMap, caizhis); registerEntityList(globalIdMap, mupis); registerEntityList(globalIdMap, chanpins); registerEntityList(globalIdMap, chanpinZujians); registerEntityList(globalIdMap, dingdans); registerEntityList(globalIdMap, dingdanChanpins); registerEntityList(globalIdMap, dingdanBancais); registerEntityList(globalIdMap, kucuns); registerEntityList(globalIdMap, zujians); registerEntityList(globalIdMap, users); registerEntityList(globalIdMap, jinhuoList); } /** * 注册单个实体列表到全局映射表 */ private static void registerEntityList(Map<Integer, Object> globalIdMap, SynchronizedList<? extends EntityClassGrassrootsid> list) { for (EntityClassGrassrootsid entity : list) { Object original = getOriginalEntity(entity); if (original instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid e = (EntityClassGrassrootsid) original; if (e.getId() != null) { globalIdMap.put(e.getId(), original); } } } } /** * 解析所有实体的引用关系 */ private static void resolveAllReferences(Map<Integer, Object> globalIdMap) { resolveListReferences(bancais, globalIdMap); resolveListReferences(caizhis, globalIdMap); resolveListReferences(mupis, globalIdMap); resolveListReferences(chanpins, globalIdMap); resolveListReferences(chanpinZujians, globalIdMap); resolveListReferences(dingdans, globalIdMap); resolveListReferences(dingdanChanpins, globalIdMap); resolveListReferences(dingdanBancais, globalIdMap); resolveListReferences(kucuns, globalIdMap); resolveListReferences(zujians, globalIdMap); resolveListReferences(users, globalIdMap); resolveListReferences(jinhuoList, globalIdMap); } /** * 解析列表内所有实体的引用 */ private static void resolveListReferences(SynchronizedList<?> list, Map<Integer, Object> globalIdMap) { for (Object entity : list) { resolveEntityReferences(entity, globalIdMap); } } /** * 解析单个实体的所有字段引用 */ private static void resolveEntityReferences(Object entity, Map<Integer, Object> globalIdMap) { if (entity == null) return; Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { try { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 1. 处理直接实体引用 if (value instanceof EntityClassGrassrootsid) { resolveDirectReference(entity, field, (EntityClassGrassrootsid) value, globalIdMap); } // 2. 处理集合类引用 else if (value instanceof Collection) { resolveCollectionReferences(entity, field, (Collection<?>) value, globalIdMap); } } catch (Exception e) { Log.e("Data", "解析字段错误: " + field.getName(), e); } } } /** * 解析直接实体引用 */ private static void resolveDirectReference(Object entity, Field field, EntityClassGrassrootsid ref, Map<Integer, Object> globalIdMap) throws IllegalAccessException { if (ref.getId() == null) return; Object resolved = globalIdMap.get(ref.getId()); if (resolved != null && field.getType().isAssignableFrom(resolved.getClass())) { field.set(entity, resolved); } } /** * 解析集合中的引用 */ private static void resolveCollectionReferences(Object entity, Field field, Collection<?> collection, Map<Integer, Object> globalIdMap) throws IllegalAccessException { // 创建新集合保留解析后的实体 Collection<Object> resolvedCollection = new ArrayList<>(collection.size()); for (Object item : collection) { if (item instanceof EntityClassGrassrootsid) { EntityClassGrassrootsid ref = (EntityClassGrassrootsid) item; Object resolved = globalIdMap.get(ref.getId()); if (resolved != null) { resolvedCollection.add(resolved); } else { resolvedCollection.add(item); // 保留原对象(可能只是占位符) } } else { resolvedCollection.add(item); } } // 替换集合 field.set(entity, resolvedCollection); } /** * 获取原始实体(非代理对象) */ private static Object getOriginalEntity(Object entity) { try { if (entity instanceof SynchronizableEntity) { // 检查是否有getOriginal()方法 Method getOriginal = entity.getClass().getMethod("getOriginal"); return getOriginal.invoke(entity); } return entity; } catch (Exception e) { return entity; // 如果反射失败返回原对象 } } ``` ### 代码解析: 1. **全局ID映射表** - 创建包含所有实体的全局映射表 `globalIdMap` - 关键优势:允许快速查找任意实体 2. **三阶段解析流程**: ```mermaid graph TD A[数据加载完成] --> B[注册所有实体到ID映射表] B --> C[解析所有实体引用] C --> D[解析集合类型引用] ``` 3. **引用解析类型处理**: - **直接引用**:如 `Bancai` → `Caizhi` - **集合引用**:如 `Dingdan` → `List<Dingdan_Chanpin>` 4. **安全解析机制**: - 使用反射动态访问私有字段 - 完善的异常处理 - 保持原始数据不变性 5. **代理对象处理**: - 检查并获取原始实体对象 - 确保解析基于实际数据对象 ### 核心优势: 1. **全面性**: - 处理所有可能的引用类型 - 覆盖嵌套和复杂引用场景 2. **性能优化**: - O(1)时间复杂度的实体查找 - 避免多层嵌套循环 3. **健壮性**: - 安全处理部分关联数据缺失的情况 - 保持对象图的完整一致性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值