Const interface to complex objects

Wolf0403 2007-04-16 02:26:50
如秃子老大指出,当从 getter method 返回 mutable object 时总会“心惊胆战”,因为 Java 没有提供一种语法上的强制措施保证返回的引用不会被用于修改对象本身的属性。余尝求解于此。

public I getImmutable() {
return (I)Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {I.class}, new InvocationHandler() {

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().startsWith("set")) {
throw new UnsupportedOperationException("Unmodifiable");
}
return method.invoke(proxy, args);
}

});
}

方案是基于 setXXX 的命名习惯,且所有 setXXX 均须来自某 interface,因此基本算是。。完全没有意义。:(

另外一种方法是纯粹的手工操作

public Immutable getImmutable() {
return new Immutable() {

@Override
public void setI(int i) {
throw new UnsupportedOperationException("Unmodifiable");
}
// 一一添加其它需要禁用的方法
};
}

16日凌晨失眠乱写于此。
...全文
289 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
coder_hui 2008-07-21
  • 打赏
  • 举报
回复
我对public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
这个方法很是迷惑,哪位高手可以指点一下?

为什么这个方法会自动执行?

第一个参数是什么呢? JAVA随便给的吗?
Wolf0403 2007-04-18
  • 打赏
  • 举报
回复
老大点评 相当到位 - -b
Wolf0403 2007-04-16
  • 打赏
  • 举报
回复
补充:

现有的 Java Collection Framework 中,对于任一 Collection c; 可以通过 java.util.Collections.unmodifiableCollection ( c ); 得到的 immutable collection (类型为传入 Collection 接口的实例)就是这样行为的。对任何 put / add 等操作,都在 runtime 抛这个异常(UnsupportedOperationException 是一个 RuntimeException 派生类,所以可以绕过 Checked Exception 声明限制)。

再补充:

实际一想,JCF 中 Collection, Map, List, Set, SortedMap, SortedSet 都是接口,所以通过 Proxy 是可以方便实现的。

最后补充:

看了一下 JCF Collections 类的实现,实际是对一个 T c,直接返回一个 new UnmodifiableT(c);
Wolf0403 2007-04-16
  • 打赏
  • 举报
回复
1. 总觉得 Java 是很依赖工具的一个语言。。@deprecated, Java5 的 Annotation,甚至有 BCEL 一类的古怪东西。。
3. UnsupportedOperationException 似乎是 Java 对这种情况的标准处理。。因为 Collection Framework 中 java.util.Collections.unmodifiable* 返回的对象就是具有这样的行为特征。

C++ 中,避免修改可以有两种形式。一种是 return by value,通常针对的是 simple / value type;一种是返回 const ref,通常针对复制代价较大(或禁止复制)的对象。get_const 基本是 rbv 的做法,而偶的方法是类似 const ref 的做法。

第二点是个问题。但是我猜想,get/setter 访问的属性,通常还是以值类型为主吧。Collection 就是另外的故事了。对于 const obj 而言,最好的方法还是通过语言/VM保证。
wingfiring 2007-04-16
  • 打赏
  • 举报
回复
这两个方案一定程度上是可以解决问题的。但是,有下面几个不足:
1。两个方案给出了解决的步骤,但这个步骤是语言之外处理的。
2。方法虽然不是很复杂,但是考虑到每个同样需求的地方,都要重复工作,实在麻烦。真实项目中,恐怕没人愿意这么做。
3。只能在运行期给出检测,编译期一切正常。
所以,你那天说提供两套接口,虽然可能工作量更大,我觉得反而简单,因为容易说明白。

受到C++中值返回的启发,我想到的一个方案是:
public I get() {return m_i;}
public I get_const() {return m_i.deepClone();}
这个方案最大问题在性能上,可能又不小的损失。另外,还要求用户必须正确实现deepClone的语义。但我想,优点在于简单,实际项目中比较容易贯彻。对于Cpper来说,和C++的风格也较接近。

总之,我觉得,对于cpper来说,没有const,是一种缺失。
Wolf0403 2007-04-16
  • 打赏
  • 举报
回复
辅助工具解决方案:

Q1:Eclipse -> Refactor -> Extract Interface
Q2:Eclipse -> Source -> Override/Implement Methods
lw1a2 2007-04-16
  • 打赏
  • 举报
回复
发错地方乎
BluntBlade 2007-04-16
  • 打赏
  • 举报
回复
……
晨星 2007-04-16
  • 打赏
  • 举报
回复
倘若上面的代码都是晨星所写,令废人评之,必言“龌龊”。。。。
:P
晨星 2007-04-16
  • 打赏
  • 举报
回复
先占个坑

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧