在这篇文章中,我们将为您详细介绍谷歌的ImmutableList和Collections.unmodifiableList的内容,并且讨论关于有什么区别?的相关问题。此外,我们还会涉及一些关于Coll
在这篇文章中,我们将为您详细介绍谷歌的ImmutableList和Collections.unmodifiableList的内容,并且讨论关于有什么区别?的相关问题。此外,我们还会涉及一些关于Collections.emptyList()和Collections.EMPTY_LIST有什么区别、Collections.unmodifiableCollection、Collections.unmodifiableList 方法的使用与场景、Collections.unmodifiableList和防御性副本的知识,以帮助您更全面地了解这个主题。
本文目录一览:- 谷歌的ImmutableList和Collections.unmodifiableList()有什么区别?(google list)
- Collections.emptyList()和Collections.EMPTY_LIST有什么区别
- Collections.unmodifiableCollection
- Collections.unmodifiableList 方法的使用与场景
- Collections.unmodifiableList和防御性副本
谷歌的ImmutableList和Collections.unmodifiableList()有什么区别?(google list)
从ImmutableList javadocs:
与Collections.unmodifiableList(java.util.List)(它是仍可以更改的单独集合的视图)不同,ImmutableList实例包含其自己的私有数据,并且永远不会更改。ImmutableList对于公共静态最终列表(“常量列表”)非常方便,并且还使您可以轻松地创建由调用者提供给您的类的列表的“防御性副本”。
这是否意味着:
- 如果我有Dimension对象的ImmutableList(例如),那么我无法更改其中的任何Dimension对象?
- 如果我有Dimension对象的Collections.unmodifiableList(列表),那么我不仅只能添加或删除任何对象,而且可以更改它们(例如,调用setDimension(width,height)方法)?
答案1
小编典典不,不变性仅适用于中的对象的数量和引用Collection
,而不能解决您放入中的对象的可变性Collection
。
不可变列表优于标准JDK的地方Collections.unmodifiableList
在于,通过使用ImmutableList
该列表,可以确保所引用的对象,它们的顺序和列表的大小不会从任何源更改。随着Collections.unmodifiableList
如果别的东西有基础列表的引用,该代码可以修改列表,即使你有一个不可修改的列表的引用。
但是,如果要实现真正的不变性,则必须用不变的对象填充列表。
Collections.emptyList()和Collections.EMPTY_LIST有什么区别
在Java中,我们具有Collections.emptyList()和Collections.EMPTY_LIST。两者具有相同的属性:
返回空列表(不可变)。该列表是可序列化的。
那么使用一个或另一个之间的确切区别是什么?
Collections.unmodifiableCollection
Collections.unmodifiableCollection这个可以得到一个集合的镜像,它的返回结果不可直接被改变,否则会提示
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1018)
为了就是保护数据不要被改变。另外,修改原Collections时,会同时修改对应的镜像。
public class CollectionsTest {
@Test
public void test(){
Collection<String> c = new ArrayList<String>();
Collection<String> s = Collections.unmodifiableCollection(c);
c.add("str");
System.out.println(s);
}
}
此时c集合被修改,s集合也会发生变化。
Collections.unmodifiableList 方法的使用与场景
在《重构 —— 改善既有代码的设计》一书中,有一种重构手法叫 Encapsulate Collection
(封装集群),为了演示该重构手法,我写了四个类,通过对比重构前后的代码,加深对
这一重构手法的理解。
类 Student 有一 ArrayList 属性,如果没有阅读《重构 —— 改善既有代码的设计》一书,
很多人可能会像我一样,如下设计类 Student。但是,如果通过 Student.getCourses ()
获得对 ArrayList 属性引用后,就可以任意为 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 对象添加一个新课程。就好像,你必须让顾客自己向购物车里放食物,
而不能在顾客毫不知情下,偷偷向其购物车里放食物。
Collections.unmodifiableList和防御性副本
如果我写
List<Integer> a1 = Arrays.asList(1,2,3);
List<Integer> a2 = Collections.unmodifiableList(a1);
a2
是只读的,但是如果我写
a1.set(0,10);
然后a2
也被修改。
如果在API中表示:
返回指定集合的不可修改视图。此方法允许模块为用户提供对内部集合的“只读”访问权限。
那么,为什么如果我修改原始集合又修改了目标复制的集合?
也许我误解了含义,如果是的话,写一份防御性副本的方式是什么?
关于谷歌的ImmutableList和Collections.unmodifiableList和有什么区别?的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Collections.emptyList()和Collections.EMPTY_LIST有什么区别、Collections.unmodifiableCollection、Collections.unmodifiableList 方法的使用与场景、Collections.unmodifiableList和防御性副本的相关信息,请在本站寻找。
本文标签: