注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

让一切都逝去吧

排骨炖泥菜/猪肝炒苹果/鱼籽狗肉汤/狗头薏米汤

 
 
 

日志

 
 

不可变对象  

2009-10-03 17:22:26|  分类: reading |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

        有时有些需求要求一个类创建后不会被修改,单例类可以保证当前类只有一个,但有时候需要保证这个类的属性也不会被修改。如下,
public class Book {
   private  String title;
   public void setTitle(String title) {
          this.title = title;
   }
   public String getTitle() {
          return title;
   }
}
       这个简单类是可变的,调用setTitle方法就可以修改它的属性值。可以修改其title为final使其不可改变。如果该类有个数组类型的属性,则即使声明为final的,其数组元素的值仍可进行修改,这时可以用集合来代替数组,如List 。
import java.util.Collections;
import java.util.List;

public class BetterAddressBook {
    private final List<String> names;
    public BetterAddressBook(List<String> names) {
        this.names = Collections.unmodifiableList(names);
    }
    public List<String> getNames() {
        return names;
    }
}
       这个时候,
BetterAddressBook book = new BetterAddressBook(Arrays.asList("Landau", "Weinberg", "Hawking"));
book.getNames().add(0, "Montana");
       这样的调用方法,编译时没有错误,但执行时会抛出一个java.lang.UnsupportedOperationException异常。但是另一种写法,仍然可以修改BetterAddressBook实例的属性:
    List<String> physicists = new ArrayList<String>();
    physicists.addAll(Arrays.asList("Landau", "Weinberg", "Hawking"));
    BetterAddressBook addrBook1 = new BetterAddressBook(physicists);
    physicists.add("Einstein");
       最后一句添加成功,其内部元素有Landau、Weinberg、Hawking、Einstein四个。
       为了保持不可变性,继续进行修改:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hibernate.annotations.Immutable;

@Immutable
public class BestAddressBook {
    private final List<String> names;

    public BestAddressBook(List<String> names) {
        this.names = Collections.unmodifiableList(new ArrayList<String>(names));  //★
    }

    public List<String> getNames() {
        return names;
    }
}
       与上一个类不同之处在于★标注那行,重新创建了ArrayList对象。我们对于对BestAddressBook 类实例做任意修改:
    List<String> physicists = new ArrayList<String>();
    physicists.addAll(Arrays.asList("Landau", "Weinberg", "Hawking"));
    BestAddressBook addrBook2 = new BestAddressBook(physicists);
    physicists.clear();
    physicists.add("Darwin");
    physicists.add("Wallace");
    physicists.add("Dawkins");
        而addrBook2内的元素依然只有,"Landau", "Weinberg", "Hawking"这三个。

        BestAddressBook 类这样的写法并不能百分百保证类不可变,这里不可变的原因是由于其最终的子元素String类是final的。考虑下面这个类,拥有最开始的Book类型的属性:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.hibernate.annotations.Immutable;

@Immutable
public class Liberary {
    private final List<Book> books;

    public Liberary(List<Book> books) {
        this.books = Collections.unmodifiableList(new ArrayList<Book>(books));
    }

    public List<Book> getBooks() {
        return books;
    }
}
       使用下面测试代码:
  Book book = new Book();
  book.setTitle("Dependency Injection");
  Liberary liberary = new Liberary(Arrays.asList(book));
  liberary.getBooks().get(0).setTitle("The Tempest");
      最后一行的setTitle方法更改标题成功,因此,在声明一个“不可变”的对象以前,仔细地检查它依赖的每一个对象也都是安全不可变的。@Immutable标注是hibernate-annotations包内的,它标明当前需要检查可变性,这个标注它本身什么都不做,只是提醒你,应该去检查当前类所依赖的每一个对象是否都是不可变的。

      原文:http://www.infoq.com/cn/articles/dhanji-prasanna-concurrency

  评论这张
 
阅读(1256)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017