我可以看到Collections.unmodifiableSet
返回給定集的不可修改視圖,但我不明白爲什麼我們不能只使用final
修改器來實現此目的。Collections.unmodifiableSet()在Java中做什麼?
在我的理解中,final
聲明瞭一個常量:無法修改的東西。所以,如果一個集合被聲明爲一個常量,那麼它就不能被修改:任何東西都不能被刪除,也不能添加任何東西。我們需要Collections.unmodifiableSet
?
我可以看到Collections.unmodifiableSet
返回給定集的不可修改視圖,但我不明白爲什麼我們不能只使用final
修改器來實現此目的。Collections.unmodifiableSet()在Java中做什麼?
在我的理解中,final
聲明瞭一個常量:無法修改的東西。所以,如果一個集合被聲明爲一個常量,那麼它就不能被修改:任何東西都不能被刪除,也不能添加任何東西。我們需要Collections.unmodifiableSet
?
final
聲明瞭一個不能修改的對象引用,例如,
private final Foo something = new Foo();
創建一個新的Foo
,並將在something
參考。此後,無法將something
更改爲指向Foo
的不同實例。
這樣做不是防止修改對象的內部狀態。我仍然可以調用Foo
上的任何方法,這些方法可以訪問相關範圍。如果其中一個或多個方法修改該對象的內部狀態,則final
不會阻止該內容。
這樣,執行以下操作:
private final Set<String> fixed = new HashSet<String>();
確實不創建Set
不能被添加到或以其它方式改變;它只是意味着fixed
只會引用該實例。
相反,這樣做的:
private Set<String> fixed = Collections.unmodifiableSet(new HashSet<String>());
創建Set
的一個實例,它會拋出UnsupportedOperationException
如果試圖調用fixed.add()
或fixed.remove()
,例如 - 對象本身會保護其內部狀態,並防止它被修改。
爲了完整起見:
private final Set<String> fixed = Collections.unmodifiableSet(new HashSet<String>());
創建一個Set
,將不允許其內部狀態改變,也意味着fixed
僅會指向該組的一個實例的實例。
final
可用於創建基元常量的原因是基於值無法更改的事實。請記住,上面的fixed
只是一個參考 - 一個包含無法更改地址的變量。那麼,對於原語,例如
private final int ANSWER = 42;
的ANSWER
值是42.由於ANSWER
不能改變,那就只能永遠擁有價值42
是模糊的所有行會是這樣的一個例子:
private final String QUESTION = "The ultimate question";
根據以上規則,QUESTION
包含String
的一個實例的地址,該實例代表「最終問題」,並且該地址不能更改。這裏要記住的是String
本身是不可變的 - 你不能對String
的一個實例進行任何修改,並且任何其他操作(如replace
,substring
等)都會返回對完全不同的引用String
的實例。
final
只保證參考到變量代表的對象不能被改變它不會爲對象的實例和它的可變性做任何事情。
final Set s = new Set();
只是保證你不能再做s = new Set();
。它不會使得這個集合不可修改,它如果你不能添加任何東西來開始。所以要說清楚,final
隻影響變量參考不是對象的參考指向。
我可以做到以下幾點:
final List<String> l = new ArrayList<String>();
l.add("hello");
l.add("world");
l.remove(0);
,但我不能這樣做。因爲final
我不能修改變量l指向什麼。
您必須執行以下三件事之一才能使Collection容器線程安全。
java.util.Collections.syncronizedXXX();
或
java.util.Collections.unmodifiableXXX();
或 使用從java.util.concurrency.* package
適當容器中的一個。
,如果我有一個Person
對象,做final Person p = new Person("me");
這意味着我不能重新分配p
指向另一個Person
對象。我仍然可以做p.setFirstName("you");
什麼混淆的情況是,
final int PI = 3.14;
final String greeting = "Hello World!";
樣子const
在C++中,而事實上它們指向的對象是不可改變/不可改變的天性。具有可以改變對象內部狀態的增變器方法的容器或對象不是const
只是參考那些對象是final
並且不能被重新分配到參考另一個對象。
final
不是(C++風格)const
。與C++不同,Java沒有const
-方法或類似的東西,可以通過final
引用來調用可以更改對象的方法。
Collections.unmodifiable*
是一個包裝,它強制(僅在運行時,不在編譯時)爲相關集合設置只讀屬性。
的Collections.unmodifiableSet(Set<? extends T>)
將在原來設置創建包裝。這個包裝套件不能被修改。但仍然可以修改原始設置。
實施例:
Set<String> actualSet=new HashSet<String>(); //Creating set
添加一些元素
actualSet.add("aaa");
actualSet.add("bbb");
印刷添加元素
System.out.println(actualSet); //[aaa, bbb]
把actualSet
成不可修改的組和分配給新的參考(wrapperSet
)。
Set<String> wrapperSet=Collections.unmodifiableSet(orginalSet);
打印wrapperSet。所以它有actualSet
值
System.out.println(wrapperSet); //[aaa, bbb]
讓嘗試刪除/上wrapperSet
添加一個元素。
wrapperSet.remove("aaa"); //UnSupportedOperationException
在actualSet
actualSet .add("ccc");
打印actualSet
和wrapperSet
再添加一個元素。兩組值都相同。所以如果您添加/刪除實際設置中的任何元素,則更改也會反映在包裝設置上。
System.out.println(actualSet); //[aaa, ccc, bbb]
System.out.println(wrapperSet); // [aaa, ccc, bbb]
用法:
這Collections.unmodifiableSet(Set<? extends T>)
用於防止任何對象的設置的吸氣劑的方法的修飾。讓說
public class Department{
private Set<User> users=new HashSet<User>();
public Set<User> getUsers(){
return Collections.unmodifiableSet(users);
}
}
好貼。總之,_reference_不能改變,但是對象的_contents_可以*。 – extraneon 2010-03-10 20:20:35