日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢(xún)
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
淺談如何為Java創(chuàng)建Pair類(lèi)

Java中對(duì)于多個(gè)返回參數(shù)的選項(xiàng)是有限制的。一種方法只能返回一個(gè)對(duì)象,數(shù)組或原始函數(shù),和其他語(yǔ)言不同的是它不會(huì)提供一種簡(jiǎn)易方式來(lái)消耗方法調(diào)用中的參數(shù)。實(shí)際上我們的選擇是返回一個(gè)對(duì)象數(shù)組,一個(gè)集合,僅為返回的參數(shù)創(chuàng)建一個(gè)類(lèi),或者最終將其發(fā)送到你打算替換的對(duì)象中。所有這些方法都存在缺陷:
使用對(duì)象數(shù)組

如果我們能夠幸運(yùn)地獲取一套同類(lèi)的返回參數(shù),那么對(duì)象的數(shù)組就會(huì)是一個(gè)帶有例外的選項(xiàng),當(dāng)我們打開(kāi)這些對(duì)象時(shí)需要能分辨出每個(gè)參數(shù)。從另一方面來(lái)說(shuō),如果我們正在返回多個(gè)參數(shù)的不同類(lèi)型,我們需要使用所有超類(lèi)對(duì)象的數(shù)組--最有可能的就是對(duì)象本身。然后我們要拋出每一個(gè)打開(kāi)的參數(shù)。我們已經(jīng)丟失了類(lèi)型安全性且返回參數(shù)命令出錯(cuò)的機(jī)會(huì)也可能增加。

使用集合

與使用數(shù)組的方法類(lèi)似,我們或許也能創(chuàng)造一個(gè)集合來(lái)實(shí)現(xiàn)返回。在集合之上使用數(shù)組主要是因?yàn)閯?chuàng)建集合所需要代碼的數(shù)量要比這段代碼短:

List< Object> retVal = new ArrayList< Object>(); 
retVal.add(string1);

retVal.add(num2);

retVal.add(object3);

return retVal; 
而創(chuàng)建集合的代碼要高于使用數(shù)組初始化設(shè)置:

return new Object[] {string1, num2, object3}

事實(shí)上在數(shù)組之上使用集合沒(méi)有什么真正的優(yōu)勢(shì),除非我們要使用映射以便通過(guò)名稱(chēng)或其他要素來(lái)返回值。

首次創(chuàng)建Java時(shí),其簡(jiǎn)單程度是對(duì)日趨復(fù)雜的c++的一種顛覆。指針和內(nèi)存管理被簡(jiǎn)化了,包括去除參數(shù)間接,常量,函數(shù)指針以及其他功能強(qiáng)大但容易混淆的性能。在c++中,我們可以用值或參照傳遞參數(shù),這樣可以對(duì)方法中的參照進(jìn)行重新分配,并為你提供參數(shù)或返回更多值的方式。

使用JavaBeans

C++也支持的structs允許簡(jiǎn)單結(jié)構(gòu)化的數(shù)據(jù)包。當(dāng)然,Java類(lèi)可以簡(jiǎn)單完成雙倍于structs的任務(wù),但通常習(xí)慣以大量模板來(lái)擴(kuò)大源碼。

使用類(lèi)和JavaBeans慣例的時(shí)候還存在一個(gè)問(wèn)題,即對(duì)象本質(zhì)上是易變的。這些對(duì)象有可能被方法的調(diào)用者和方法調(diào)用的類(lèi)共享,這樣就會(huì)導(dǎo)致易變狀態(tài)的共享,而這中情況無(wú)益于多線程系統(tǒng)。

在Java中,你能用值傳遞的只剩下方法參數(shù)了,而且還不能是outparams,同時(shí)方法只能返回一個(gè)參數(shù)??匆幌氯我獯a庫(kù)就會(huì)發(fā)現(xiàn)大量的實(shí)例,不過(guò)卻不是十分有效。

改進(jìn)Java Beans方式

那么應(yīng)該怎樣做呢?Java類(lèi)選項(xiàng)事實(shí)上才是解決方案的關(guān)鍵以及對(duì)其方式進(jìn)行改進(jìn)。這些類(lèi)可以成為structs更好的替代物。

讓我們?yōu)榉祷氐念?lèi)確定兩個(gè)參數(shù):名稱(chēng)和出生日期:

public class PersonNameDOB { 
private String name;

private Date dob;

public Date getDob() {

return dob;

}

public void setDob(Date dob) {

this.dob = dob;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}}

然這是一個(gè)人為的例子,我們有機(jī)會(huì)擁有一個(gè)已經(jīng)定義的Person類(lèi)。大家肯定也會(huì)有類(lèi)似的例子,需要從方法中返回兩個(gè)不同的對(duì)象,但是卻沒(méi)有已經(jīng)為其定義的類(lèi),或者是返回的類(lèi)夾帶多余的信息,或許是比這更糟的情況。例如,如果有人調(diào)用了你的方法來(lái)使用或修改返回對(duì)象中的值。
上述情況所需代碼更多。因此我們可以做一些簡(jiǎn)單的修改:

public class PersonNameDOB { 
public final String name;

public final Date dob;

public PersonNameDOB(String name, Date dob) {

this.name = name;

this.dob = dob;

}}

其結(jié)果要短一些且更適合這項(xiàng)任務(wù)。值已經(jīng)返回了,因此不需要setters了,我們只要在返回對(duì)象建成后創(chuàng)建值就可以了。它們不需要更改,由于它們位于構(gòu)造器中,因此具有決定性作用?,F(xiàn)在任務(wù)已經(jīng)完成,將類(lèi)的屬性設(shè)為公開(kāi)也沒(méi)有風(fēng)險(xiǎn)了。同理,可以處理getters了,其結(jié)果更短,更易于使用。

PersonNameDOB personNameDOB = SSNLookup.lookupBySSN("123-45-6789"); 
System.out.println(personNameDOB.name);

System.out.println(personNameDOB.dob);

lookupBySSN方法:

public PersonNameDOB lookupBySSN(String ssn) {

... Find the person record in the DB, etc. ...

return new PersonNameDOB(person.getName(), person.getDOB());}

 

如果這些太顯而易見(jiàn),請(qǐng)耐心看下去。我喜歡用這個(gè)方法來(lái)簡(jiǎn)化對(duì)象的返回。這種類(lèi)型是安全的,因此在返回后不需要將對(duì)象拋出數(shù)組。而最后屬性的修改意味著這些返回的對(duì)象不會(huì)被濫用--它們只是為了傳輸數(shù)據(jù)。

為了安全起見(jiàn),建議你復(fù)制對(duì)象或使用不可改變的對(duì)象以應(yīng)付值的意外修改。在我們的例子中,字符串是不可改變的,但是日期可以復(fù)制:

 public PersonNameDOB lookupBySSN(String ssn) { 
... Find the person record in the DB, etc. ...

return new PersonNameDOB(person.getName(), new Date(person.getDOB().getTime()));

}

這可以阻止調(diào)用者做接下來(lái)的操作:

 PersonNameDOB personNameDOB = SSNLookup.lookupBySSN("123-45-6789"); 
personNameDOB.dob.setTime(0);

成對(duì)的需求

以上的模式是筆者經(jīng)常在Java應(yīng)用程序接口調(diào)用中用來(lái)替代structs的方法,但是如果我們只是想返回兩個(gè)類(lèi)型對(duì)象,這些就還不夠??瓷先ナ峭偈挚傻玫臇|西其實(shí)仍然從JavaSE標(biāo)準(zhǔn)分配中神秘失蹤,而這就是被原始化的Pair類(lèi)??纯次覀?nèi)绾螐纳鲜瞿J絹?lái)建立Pair類(lèi)。

首先,值要比名稱(chēng)和出生日期都普遍。最普遍的是在將域名定為first和second:

public class Pair { 
public final String first;

public final Date second;

public Pair(String first, Date second) {

this.first = first;

this.second = second;

}}

現(xiàn)在擁有了一個(gè)可以返回Strings和Dates對(duì)的通用類(lèi),但還不包括其他類(lèi)型,將其擴(kuò)展為通用類(lèi)型:

public class Pair< A, B> { 
public final A first;

public final B second;

public Pair(A first, B second) {

this.first = first;

this.second = second;

}}

這樣就好多了。沒(méi)必要擔(dān)心代表了一對(duì)返回類(lèi)型快捷方式的通配符。這個(gè)類(lèi)現(xiàn)在可以作為通用類(lèi)型對(duì)來(lái)使用,如:

public static Pair< String, Date> lookupBySSN(String ssn) { 
// find the person in the DB....

return new Pair(person.getName(), new Date(person.getDOB().getTime()));

}

開(kāi)始使用:

Pair< String, Date> personNameDOB = SSNLookup.lookupBySSN("123-45-6789"); 
System.out.println(personNameDOB.first);

System.out.println(personNameDOB.second);

Pair類(lèi)還未完成。我們還要考慮類(lèi)型是否真具有普遍性:

1. 我們不想其他人擴(kuò)展或更改Pair類(lèi),因?yàn)檫@可能破壞類(lèi)的最初意圖。

2. 新的new Pair()是可以的,但是看上去有些不雅,我們可以改進(jìn)一下。

3. Pair對(duì)于返回值是很有效的,但是如果要作為映射中的關(guān)鍵要素就有些勉為其難。

4. 擁有用于調(diào)試或其他toString()用途的Pair字符串代表形式是非常好的。

5. 最后,允許Pair和包含的對(duì)象可被序列化,其內(nèi)容也被假定為可以序列化了。

因此,讓我們看看它是如何改變Pair執(zhí)行的:

public final class Pair< A,B> implements Serializable { 
private static final long serialVersionUID = 1L; // shouldn't

// need to change

public final A first;

public final B second;

private Pair (A first, B second) {

this.first = first;

this.second = second;

}

public static < A,B> Pair< A,B> of (A first, B second) {

return new Pair< A,B>(first,second);

}

@Override

public boolean equals(Object obj) {

if (obj == null) {

return false;

}

if (getClass() != obj.getClass()) {

return false;

}

final Pair other = (Pair) obj;

if (this.first != other.first &&

(this.first == null || !this.first.equals(other.first))) {

return false;

}

if (this.second != other.second &&

(this.second == null || !this.second.equals(other.second))) {

return false;

}

return true;

}

@Override

public int hashCode() {

int hash = 7;

hash = 37 * hash + (this.first != null ?

this.first.hashCode() : 0);

hash = 37 * hash + (this.second != null ? this.second.hashCode() : 0);

return hash;

}

@Override

public String toString () {

return String.format("Pair[%s,%s]", first,second);

}

}
 

這樣就已經(jīng)將構(gòu)造器私有化,但是提供了一個(gè)看起來(lái)更適合的靜態(tài)of()方法:

return Pair.of(person.getName(), new Date(person.getDOB().getTime()));

Pair類(lèi)已經(jīng)完成,因此沒(méi)有人可以取代它或改變類(lèi)的原始意圖。它看上去很?chē)?yán)格,但卻可以用于廣泛的使用。如果有人想讓Pair以不同方式運(yùn)作,就應(yīng)該寫(xiě)出適合自己的執(zhí)行代碼,并對(duì)其進(jìn)行求證。

equals()和hash()方法意味著這個(gè)類(lèi)不止可以用來(lái)返回值。它們還可以成為映射的關(guān)鍵。此處對(duì)使用該模式返回對(duì)象給出的建議是讓IDE為我們創(chuàng)建equals和hashCode方法。IDE往往都有可插入的模板,其中包含已定義的最佳方法,因此我們只需讓NetBeans創(chuàng)建就可以了。

toString()給出了pair的合適形式,如 "Pair[FredJones,Sun Mar 22 12:55:44 PDT 2009]"。這對(duì)于調(diào)試彈出很有用。

這一個(gè)類(lèi)現(xiàn)在執(zhí)行Serializable。相信此處我們的選擇令人懷疑,但是集合是可序列化的,Pair應(yīng)該也可以。如果Pair中的類(lèi)不能序列化那么就如果集合中的類(lèi)不能序列化一樣糟糕,而Pair不應(yīng)該阻止類(lèi)中間的序列化。

完成了嗎?

既是又不是。這個(gè)類(lèi)現(xiàn)在在Navigenics中使用。毫無(wú)疑問(wèn)在其他Java應(yīng)用程序中也存在類(lèi)似的執(zhí)行。那我們完成了沒(méi)有呢?從"最具預(yù)見(jiàn)性"的角度來(lái)講,我們完成了。從"任何時(shí)候都需要"的角度來(lái)說(shuō)恐怕還沒(méi)完成。

例如,這類(lèi)Pairs不能做比較。增加一個(gè)compareTo()方法使之可比,但是要注意應(yīng)對(duì)復(fù)雜的通用類(lèi)設(shè)計(jì)。通常,比較第一個(gè)值很容易,如果它們相等,就要比較第二個(gè)值。這可能是最合適的行為,但是Pair的每次使用都正確嗎?我們要檢查一下作比較的類(lèi)是否具有可比性,如果不具備,該怎么辦?

結(jié)論

為Java創(chuàng)建一個(gè)Pair類(lèi)是有些難的,而且在簡(jiǎn)單通用的類(lèi)庫(kù)執(zhí)行中,類(lèi)庫(kù)要求在少量功能前提下不改變Java語(yǔ)言。通用性是很麻煩的一件事。不過(guò),本人相信本文描述的Pair類(lèi)至少是SE庫(kù)中標(biāo)準(zhǔn)化Pair執(zhí)行的良好開(kāi)端。但愿在Java 7中會(huì)增加這一項(xiàng)。盡管它對(duì)于其他語(yǔ)言中的Tuple來(lái)說(shuō)是顯得有些貧乏,但是加入標(biāo)準(zhǔn)的Pair有望為我們帶來(lái)大量實(shí)用性。這種可讀性的改進(jìn)以及模板代碼的刪除都旨在減少Coin項(xiàng)目的語(yǔ)言變化。


名稱(chēng)欄目:淺談如何為Java創(chuàng)建Pair類(lèi)
網(wǎng)站地址:http://www.5511xx.com/article/coiepgs.html