关于返回值为对象类型的问题!

yushujianjava 2012-08-23 10:42:56
今天在写二叉排序数的Java实现代码时,偶然碰到一个问题,觉得有些不可思议。

通过提取,问题属于“方法的返回值为对象类型”是出现的一个疑问,问题如下:

假设我在A类中,定义了一个私有的对象型成员变量ab(属于B类对象),并且定义了公共方法getB(),其返回值就是这个B对象类型的私有变量。此时,我在C类中,用A类对象调用了getB(),返回值赋给B类对象型变量cb,因为返回对象类型时返回的就是这个对象的引用副本,此时cb就应该指向了A中私有的B类对象类型的成员变量ab。

那么,我就可以通过cb调用B类中的某些方法来改变ab的状态,也就说,在A类之外(C类中),通过cb直接成功的修改了A类的私有成员变量的状态,这是不是打破了A类封装的私有变量的访问限制?打破了其安全性?
我总觉得这有点可怕啊,是不是我有没想到的地方呢?求教高手给予解释吧,谢谢!
...全文
432 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
yushujianjava 2012-08-30
  • 打赏
  • 举报
回复
嗯,谢谢你的解答,辛苦了!你说的这个方法我实验了,的确是一个解决的办法,对于不需要完全暴露的情况,这种委托的方法很好,使得外界无法直接指向A的私有对象,而是必须通过A中定义的代理方法来间接访问B的一些方法。但是呢,当我真的需要完全暴露时,我觉得6楼说的很对,可以参考,嘿嘿!
[Quote=引用 4 楼 的回复:]

直接用getB返回B的对象确实在一定程序上破坏了封装性,当然如果你确实有必要直接返回B的对象这样做也没有问题。

如果A类的实现者只需要使用B对象的部分功能,那么最好不要直接返回B对象,而是将B中的功能委托出去,例如A类的实现者只需要使用B的test()方法,A类就可以定义一个方法叫test:
public void test(){ ab.test();}
这样就不会破坏封装性了。

……
[/Quote]
MiceRice 2012-08-30
  • 打赏
  • 举报
回复
如果你觉得危险,可以在返回之前将其 克隆(clone)。

如果类本身非常依赖于所返回对象,这种设计本身就显得不合理了。


总的来说也别觉得这是个很大的问题。

JDBC里面还能直接把整个ResultSet给你返回过来了,你也可以随便修改,也没怎么样啊?除了用起来很方便以外。
yushujianjava 2012-08-30
  • 打赏
  • 举报
回复
尤其对于实体类来说,一个公共的getter方法挺普遍的。可是忽然存在这样的问题,我总认为应该会有某种机制来应对的。
[Quote=引用 2 楼 的回复:]

如果你觉得危险,你可以不提供public的get方法的,亲。如果你提供了这样的方法,就在文档里写清楚调用这个方法带来的危险。或者干脆不公开。总之,public是你写的,你要为此负责。
[/Quote]
BadPattern 2012-08-24
  • 打赏
  • 举报
回复
泥马的,打的东西一多,就出错误了,上面"A类的实现者"应为"A类的使用者"
BadPattern 2012-08-24
  • 打赏
  • 举报
回复
直接用getB返回B的对象确实在一定程序上破坏了封装性,当然如果你确实有必要直接返回B的对象这样做也没有问题。

如果A类的实现者只需要使用B对象的部分功能,那么最好不要直接返回B对象,而是将B中的功能委托出去,例如A类的实现者只需要使用B的test()方法,A类就可以定义一个方法叫test:
public void test(){ ab.test();}
这样就不会破坏封装性了。

在具体的场景中还要看你的B类对象适不适合做为A的成员变量,A类的实现者是通过A对象来访问B,还是直接访问B来的好?这些都是具体问题具体对待的

huimiezu 2012-08-24
  • 打赏
  • 举报
回复
如果你只想返回私有成员对象,不想它被外部改变,可以加上final修饰
scbb 2012-08-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

嗯,你说得对,的确是这样的。

所以,在返回类的私有域的时候,都需要调用clone()方法。如果没有,就需要再创建该域的一个新对象返回。
[/Quote]

楼上说的的,返回数组也是这样。
注意的是,有的没有实现clone,而且clone需要多花内存的。
对外保密和内存之间需要衡量下决定怎么返回值。
countercat 2012-08-24
  • 打赏
  • 举报
回复
嗯,你说得对,的确是这样的。

所以,在返回类的私有域的时候,都需要调用clone()方法。如果没有,就需要再创建该域的一个新对象返回。
孤独人生 2012-08-23
  • 打赏
  • 举报
回复
我认为java的封装并不是完全不能操作这个成员变量,而是不能直接操作,否则的话你要成员变量还有什么意义呢?

我看到你的问题,不太懂,认为你是这个意思就这样回答了,要是真的理解错了,请lz见谅啊
nobullet 2012-08-23
  • 打赏
  • 举报
回复
如果你觉得危险,你可以不提供public的get方法的,亲。如果你提供了这样的方法,就在文档里写清楚调用这个方法带来的危险。或者干脆不公开。总之,public是你写的,你要为此负责。
qq187197647 2012-08-23
  • 打赏
  • 举报
回复
如果你能附上代码,那别人对你的问题就更清楚了

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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