[item24] 必要时进行保护性拷贝

今天看了这一张模模糊糊的,有点晕。找了几篇播客,终于看懂了。
[url]http://tonylian.iteye.com/blog/391256[/url]
[url]http://hi.baidu.com/dongbomoo/blog/item/372cf18a17c4a8789e2fb42d.html[/url]
虽然java程序是一门安全的语言(safe language)。但即使在安全语言中,如果不采取一些措施,还是无法使自己与其他的类隔离开。假设类的客户会尽一切手段来破坏这个类的约束条件,在这样的前提下,你必须保护性地设计程序。所以说,从安全的角度考虑,应该设计面对客户的不良行为时仍能保持健壮性的类,无论系统的其它部分发生什么事情,这些类的约束都可以保持为真。
为保护实例的内部信息免受攻击,对构造函数的每个可变参数进行保护性拷贝是必要的。并且使用拷贝之后的对象作为实例的组件,而不使用原始对象。

[b]例如,写了雇员这个类。我自己用的时候对其属性做一些改动稍后会被我的程序提交到后台数据库。但是前端的人员和我做接口的时候,一些查询方法需要雇员对象。但是我不想让他们对这个雇员的属性做修改后也被提交到后台数据库。
所以我可以给他们的对象都是我自己对象的拷贝。他们即使调用这个对象的一些方法改变对象的属性。后面也不会被我的程序提交到后台数据库。[/b]
[url]http://topic.csdn.net/u/20080301/20/f0ce18e9-2fc7-4f75-9058-67a8496cc8c7.html[/url]
Effective Java》保护性拷贝无非就两条原则:
一、对构造函数的可变参数进行保护性拷贝;
二、对可变域的访问方法,只返回可变域的保护性拷贝(clone)。
什么叫不可变类?如果某个类,当创建了这个类的实例后,就不允许修改它的属性值,那么它就是不可变类。如:java.lang.String 就是一个典型的不可变类创建一个不可变类可按如下步骤:
1.把属性定义为private final类型。
2.不对外公开用于修改属性的setXXX()方法。
3.只对外公开用于读取属性的getXXX()方
以下是对播客例子中的一个修改:
创建一个可变类:Item39_Person

package enhance_chapter7;

public class Item39_Person {
private String name;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Item39_Person(String name) {
super();
this.name = name;
}

public Item39_Person() {}


}

再创建一个经理类:

package enhance_chapter7;

public class Item39_Manager {
private final Item39_Person person;


public Item39_Person getPerson() {

//return this.person;
//(2)对可变域的访问方法,只返回可变域的保护性拷贝(clone)。
return new Item39_Person(person.getName());
}
public Item39_Manager(Item39_Person person){
//this.person = person;
//(1)保护性拷贝 对构造函数的可变参数进行保护性拷贝
//生成一个新的实例,和Test中的person不是同一个对象,则修改不影响this.person的值
this.person = new Item39_Person(person.getName());
}


@Override
public String toString() {

return "Manager:" + this.person.getName();
}
}


测试:

package enhance_chapter7;

public class Item39_Test {

/**
* @param args
*/
public static void main(String[] args) {
Item39_Person person = new Item39_Person();
person.setName("liangfeng366");

Item39_Manager manager = new Item39_Manager(person);
System.out.println(manager);

//攻击(1)
person.setName("liangfeng");
System.out.println(manager);

//攻击(2)
manager.getPerson().setName("liangfeng");
System.out.println(manager);




}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值