這篇文章將為大家詳細(xì)講解有關(guān)java中的Mutability可變性解析,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
扶余網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)公司!從網(wǎng)頁設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、響應(yīng)式網(wǎng)站等網(wǎng)站項(xiàng)目制作,到程序開發(fā),運(yùn)營維護(hù)。創(chuàng)新互聯(lián)公司從2013年創(chuàng)立到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)公司。
mutable(可變)和immutable(不可變)對(duì)象是我們?cè)趈ava程序編寫的過程中經(jīng)常會(huì)使用到的。
可變類型對(duì)象就是說,對(duì)象在創(chuàng)建之后,其內(nèi)部的數(shù)據(jù)可能會(huì)被修改。所以它的安全性沒有保證。
而不可變類型對(duì)象就是說,對(duì)象一旦創(chuàng)建之后,其內(nèi)部的數(shù)據(jù)就不能夠被修改,我們可以完全相信這個(gè)對(duì)象。
雖然mutable對(duì)象安全性不夠,但是因?yàn)槠淇梢员恍薷模詴?huì)有效的減少對(duì)該對(duì)象的拷貝。
而immutable對(duì)象因?yàn)椴豢筛淖儯試L試對(duì)該對(duì)象的修改都會(huì)導(dǎo)致對(duì)象的拷貝,從而生成新的對(duì)象。
我們最常使用的String就是一個(gè)immutable對(duì)象。
可變對(duì)象和不可變對(duì)象
知道了可變對(duì)象和不可變對(duì)象的不同之處之后,我們看一下怎么才能判斷這個(gè)對(duì)象是可變對(duì)象還是不可變對(duì)象呢?
首先,最簡單的一點(diǎn)就是,不可變對(duì)象創(chuàng)建之后就不能夠被修改,所以不可變對(duì)象里面基本上沒有setXXX之類的方法,而可變對(duì)象提供了setXXX這些可以修改內(nèi)部變量狀態(tài)的方法。
看一個(gè)例子java.util.Date是一個(gè)可變對(duì)象,而java.time.LocalTime是不可變對(duì)象。
看下他們的方法定義有什么區(qū)別呢?

首先是Date,我們可以看到在其中定義了很多setXXX方法。

而在LocalTime中,我們基本上看不到setXXX方法。
同時(shí)不可變對(duì)象的字段基本上都是final的,防止被二次修改。
第二,不可變對(duì)象一般來說是不可繼承的,在java中就是以final關(guān)鍵字做限定的:
public class Date public final class LocalTime
第三,不可變對(duì)象一般會(huì)隱藏構(gòu)造函數(shù),而是使用類似工廠模式的方法來創(chuàng)建對(duì)象,這樣為實(shí)例的創(chuàng)建提供了更多的機(jī)動(dòng)性。
那么如果我們想使用mutable對(duì)象,又不想被別人修改怎么辦呢?
簡單的辦法就是拷貝一份要使用的對(duì)象:
public class CopyOutput {
private final java.util.Date date;
...
public java.util.Date getDate() {
return (java.util.Date)date.clone();
}
}這里大家還要注意深拷貝和淺拷貝的問題。
既然要為mutable對(duì)象創(chuàng)建拷貝,那么相應(yīng)的mutable類也需要提供一個(gè)copy方法來協(xié)助拷貝。
這里需要考慮一個(gè)深拷貝和淺拷貝的問題。
我們知道在HashMap中怎么去查找一個(gè)key呢?先去找這個(gè)key的hash值,然后去判斷key.equals方法是否相等,考慮下面這種情況:
private final Map<Window,Extra> extras = new HashMap<>();
public void op(Window window) {
Extra extra = extras.get(window);
}op方法接收一個(gè)Window對(duì)象,然后將其當(dāng)成key從HashMap中取出對(duì)應(yīng)的value。
如果,這個(gè)時(shí)候,我們有一個(gè)類A繼承了Window,并且hash值和equals都和另外一個(gè)Window對(duì)象B相同,那么使用A這個(gè)key可以獲取到B這個(gè)key存儲(chǔ)的數(shù)據(jù)!
怎么解決這個(gè)問題呢?
Java中有一個(gè)特別的HashMap:IdentityHashMap,這個(gè)Map的key和value比較是用==而不是equals方法,所以可以有效的避免上面出現(xiàn)的問題。
private final Map<Window,Extra> extras = new IdentityHashMap<>();
public void op(Window window) {
Extra extra = extras.get(window);
}如果沒有這樣的Map可用,那么可以使用不可變對(duì)象作為key或者使用Window的私有變量,從而惡意攻擊者無法獲得這個(gè)變量。
public class Window {
/* pp */
class PrivateKey {
Window getWindow() {
return Window.this;
}
}
final PrivateKey privateKey = new PrivateKey();
private final Map<Window.PrivateKey,Extra> extras =
new WeakHashMap<>();
...
}
public class WindowOps {
public void op(Window window) {
// Window.equals may be overridden,
// but safe as we don't use it.
Extra extra = extras.get(window.privateKey);
...
}
}如果一個(gè)可變類中的某個(gè)屬性確實(shí)需要暴露被外部使用,那么一定要將這個(gè)屬性定義為private,并且使用wrapper方法將其包裝起來。
如果直接暴露出去,那么基本上就沒有權(quán)限控制可言,任何程序只要能夠拿到你這個(gè)對(duì)象,就可以對(duì)屬性進(jìn)行修改。考慮下下面的應(yīng)用方式,我們?cè)谛薷膕tate的方法中加入了一個(gè)參數(shù)校驗(yàn)和權(quán)限控制。
public final class WrappedState {
// private immutable object
private String state;
// wrapper method
public String getState() {
return state;
}
// wrapper method
public void setState(final String newState) {
this.state = requireValidation(newState);
}
private static String requireValidation(final String state) {
if (...) {
throw new IllegalArgumentException("...");
}
return state;
}
}同樣的,如果你是一個(gè)類變量,當(dāng)然不希望這個(gè)變量會(huì)被任何人修改,那么需要將其置位final。
public class Files {
public static final String separator = "/";
public static final String pathSeparator = ":";
}如果類變量是public static final的,那么這個(gè)變量一定要是不可變的。
有人會(huì)問了,都定義成了final了,是不是就已經(jīng)不可變了?
其實(shí)不然,比如我們定義了一個(gè)final的List,雖然這個(gè)list不能變化,但是list里面的值是可以變化的。我們需要將可變變量修改為不可變變量,如下所示:
import static java.util.Arrays.asList; import static java.util.Collections.unmodifiableList; ... public static final List<String> names = unmodifiableList(asList( "Fred", "Jim", "Sheila" ));
如果使用JDK9中引入的of()或者ofEntries()方法,可以直接創(chuàng)建不可修改的集合:
public static final List
<String> names =
List.of("Fred", "Jim", "Sheila");關(guān)于java中的Mutability可變性解析就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
文章標(biāo)題:java中的Mutability可變性解析
網(wǎng)站鏈接:http://chinadenli.net/article18/pggpgp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、App設(shè)計(jì)、響應(yīng)式網(wǎng)站、網(wǎng)站設(shè)計(jì)、小程序開發(fā)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)