防御式拷贝的局限性
不管是在课程中,还是在网络中浏览,我们都可以看到,大家对防御式拷贝的理解大致就是:
对输入的mutable引用类型做拷贝再引入rep,对要输出的rep的mutable引用类型做拷贝再输出。
我们都认为这样就是表示泄露的标准预防方式。
这里想探讨一个问题,对于实验二中的ConcreteVertexGraph中的vertices方法,如若按如下返回,rep中的所有内容是否会有更改风险?
可能我们都会认为,返回的是一个新的独立的set,对它进行更改删除添加不会对rep中set的结构产生影响。但是这里想说的是,认为它极有可能会对Set中的每一个元素产生影响。
由引用类型的定义不难发现,对于Set中的一个元素泛型L,如若L是一个引用类型且是mutable的,我们就可能有机会通过返回的新Set使用其中一个元素的mutator方法,改变其值,来对Rep造成一些变化。假使原先的RI对输入的vertex的值有一定的要求,很难说在这么一通操作之后,RI条件是否还能得到满足。
那么怎么考虑这个问题呢?首先,既然原先的数据类型是泛型,我们无从得知其会运用于具体的什么类型,类型内部是什么结构(field),也就无法再防御式拷贝的阶段构造新的类型再加入set中。
但是,经查,如果该类型实现了其深拷贝的clone方法(前提是它的field中的各个mutable类型也实现了深拷贝的clone方法,层层递归下去),理应能实现这个目标。
java貌似不像C语言一样,可以用memcpy函数来无视这些实现深拷贝。但是据我们实验课上的助教所言(做实验二时),一般不会考虑用户去做这种头疼的修改。
在网上搜索到了好多种貌似深拷贝,实则浅拷贝的一些假的实现方案。在此尝试以此为基础讨论防御式拷贝。很可能对java和教的软件构造有一些基础上的理解错误。还是不妨就此记录一下,若是看到此文,请谨慎相信。