Collections.unmodifiableList方法的使用与场景

399 篇文章 12 订阅
143 篇文章 1 订阅

在公司接触到 Collections.unmodifiableList(List<? extends T> list)) 觉得用法挺特殊的,所以学习了下,简单而言,看名字就知道,将参数中的List返回一个不可修改的List。

觉得以下这篇文章写得很好,说明了它的应用场景。


在《重构——改善既有代码的设计》一书中,有一种重构手法叫Encapsulate Collection(封装集群),为了演示该重构手法,我写了四个类,通过对比重构前后的代码,加深对这一重构手法的理解。
 
类Student有一ArrayList属性,如果没有阅读《重构——改善既有代码的设计》一书,很多人可能会像我一样,如下设计Student。但是,如果通过Student.getCourses()获得对ArrayList属性引用后,就可以任意为Student对象添加“课程”,而Student对象对此一无所知,这不符合面向对象编程的习惯。

重构前

Student类:

package com.readonlylist;
import java.util.ArrayList;

public class Student {
    private String name;
    private ArrayList<String> courses;

    public Student(String name, ArrayList<String> courses) {
        this.name = name;
        this.courses = courses;
    }

    public ArrayList<String> getCourses() {
        return courses;
    }

    public void setCourses(ArrayList<String> courses) {
        this.courses = courses;
    }

    public String getName() {
        return name;
    }

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

测试:

package com.readonlylist;
import java.util.ArrayList;

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("001");
        list.add("002");
        Student s = new Student("Tom", list);

        ArrayList<String> anotherList = s.getCourses();
        anotherList.add("999");

        System.out.println("Tom's course.length = " + s.getCourses().size());
    }
}

重构后

Student类:

package com.readonlylist;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Student1 {
    private String name;
    private ArrayList<String> courses;

    public Student1(String name, ArrayList<String> courses) {
        this.name = name;
        this.courses = courses;
    }

    public String getName() {
        return name;
    }

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

    public void addCourse(String course) {
        courses.add(course);
    }

    public String removeCourse(String course) {
        boolean removed = courses.remove(courses);

        if (removed) {
            return course;
        } else {
            return null;
        }
    }

    public List<String> getCourses() {
        return Collections.unmodifiableList(courses);
    }
}

测试:

package com.readonlylist;

import java.util.List;
import java.util.ArrayList;

public class Test1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        list.add("001");
        list.add("002");
        Student1 s = new Student1("Tom", list);

        List<String> anotherList = s.getCourses();

        /**
         * throws java.lang.UnsupportedOperationException
         * should replace with s.addCourse(String course)
         */
        anotherList.add("999");

        //never reached
        System.out.println("Tom's course.length = " + s.getCourses().size());
    }
}

重构后,Student1类,仅对外提供的getCourses()方法,而没有setCourses()方法。

而且通过getCourses()方法获得的courses是“只读的”,如果你试图向其添加一个新课程,则抛出java.lang.UnsupportedOperationException。
你必须通过Student1.addCourse()来向特定的Student1对象添加一个新课程。

就好像,你必须让顾客自己向购物车里放食物,而不能在顾客毫不知情下,偷偷向其购物车里放食物。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值