Java类与线程安全集合不可变
假设我有以下类:Java类与线程安全集合不可变,java,multithreading,thread-safety,immutability,Java,Multithreading,Thread Safety,Immutability,假设我有以下类: public final class Person { final private String personFirstName; final private String personLastName; final private ConcurrentMap<Double, String> phoneMessages; public Person(String firstname, String lastname) {
public final class Person {
final private String personFirstName;
final private String personLastName;
final private ConcurrentMap<Double, String> phoneMessages;
public Person(String firstname, String lastname) {
phoneMessages = new ConcurrentHashMap<Double, String>();
this.personFirstName = firstname;
this.personLastName = lastname;
}
public void add(Double key, String item) {
phoneMessages.put(key, item);
}
public String getPersonFirstName() {
return personFirstName;
}
public String getPersonLastName() {
return personLastName;
}
}
公共最终课程人员{
最终私有字符串personFirstName;
最后一个私有字符串personLastName;
最终私有ConcurrentMap电话消息;
公众人物(字符串名、字符串名){
phoneMessages=新的ConcurrentHashMap();
this.personFirstName=firstname;
this.personLastName=lastname;
}
公共无效添加(双键,字符串项){
phoneMessages.put(键、项);
}
公共字符串getPersonFirstName(){
返回personFirstName;
}
公共字符串getPersonLastName(){
返回personLastName;
}
}
即使我创建了一个带有私有最终线程安全集合的类,我的类是不可变的吗?我猜不是
如果在对象中拥有集合不是正确的做法,那么Java中的正确做法是什么?我将如何设计包含集合的类?正如其他人所指出的,如何使用类将决定使其不可变是否合适 也就是说,您的
Person
类的这个版本是不可变的:
public final class Person {
final private String personFirstName;
final private String personLastName;
final private ConcurrentMap<Double,String> phoneMessages;
public Person(String firstname, String lastname) {
this.phoneMessages = new ConcurrentHashMap<Double,String> ();
this.personFirstName = firstname;
this.personLastName = lastname;
}
private Person(String firstname, String lastname, ConcurrentHashMap<Double,String> phoneMessages) {
this.personFirstName = firstname;
this.personLastName = lastname;
this.phoneMessages = phoneMessages;
}
public Person add(Double Key, String item){
ConcurrentHashMap<Double, String> newMap = new ConcurrentHashMap<>(this.phoneMessages);
newMap.put(Key, item);
return new Person(this.personFirstName, this.personLastName, newMap);
}
public String getPersonFirstName() {
return personFirstName;
}
public String getPersonLastName() {
return personLastName;
}
public Map<Double, String> getPhoneMessages() {
return Collections.unmodifiableMap(this.phoneMessages);
}
}
公共最终课程人员{
最终私有字符串personFirstName;
最后一个私有字符串personLastName;
最终私有ConcurrentMap电话消息;
公众人物(字符串名、字符串名){
this.phoneMessages=新的ConcurrentHashMap();
this.personFirstName=firstname;
this.personLastName=lastname;
}
私人(字符串firstname、字符串lastname、ConcurrentHashMap phoneMessages){
this.personFirstName=firstname;
this.personLastName=lastname;
this.phoneMessages=phoneMessages;
}
公众人物添加(双键,字符串项){
ConcurrentHashMap newMap=新ConcurrentHashMap(this.phoneMessages);
newMap.put(键、项);
返回新人员(this.personFirstName、this.personLastName、newMap);
}
公共字符串getPersonFirstName(){
返回personFirstName;
}
公共字符串getPersonLastName(){
返回personLastName;
}
公共映射getPhoneMessages(){
返回Collections.unmodifiableMap(this.phoneMessages);
}
}
请注意,
add
方法返回一个不同的Person
实例,因此当前的Person
实例保持不变(不变)。为什么这不是正确的做法?不是所有的东西都需要是不变的。@JBNizet-我已经等了很长时间了。我在读关于不可变类的书,而我对可变类的印象是否定的!我开始重新思考我的很多代码,这个问题出现了,所以它的设计方式,你会离开它吗?你不会改变什么吗?又一次。关于你的代码我只知道这个类。我不知道你打算用它做什么,它的使用环境,等等。因此,不可能推荐一种设计而不是另一种。你将创建另一个地图,以及使用该地图的另一个人实例。根据定义,不可变对象在创建后可能无法修改。如果我只想返回集合,是否可以返回只读类型的集合?而不是使用地图获取新的Person对象。我想问的是,我是否可以实现一个返回只读集合的getter。你可以使用Collections.unmodifiableMap
(请参阅我编辑的文章)。但是您最关心的保持不变性的方法应该是add
,它们可以更改对象的内部状态。为了在这些情况下保持不变性,您必须创建一个新的Person
实例,并将更改应用于该新实例而不是当前实例。这与String
上的某些方法的工作原理非常相似(例如replace
)。