java 方法參數過多,怎麼處理?

本人對java的研究甚少,之前只是用一用,從未有過深度的學習,但卻意外的發現了一個問題,那就是java的參數過多會出現錯誤,你們可能會認爲,我找到的這個問題沒有任何意義,對,我也是這樣想的,可是,你們不妨來聽我講一講,看看是否是這樣的道理,若是不是,也請大神們提出錯誤,並給我一個合適的答案,讓個人知識也可以有所提高,具體錯誤可見截圖:
java


 

固然,這個錯誤不只使用javac進行編譯的時候會報錯,並且在eclipse中也會報錯,錯誤內容一致,參數過多web

在這裏我提出瞭如下幾個問題:編程

1.java的方法到底支持多少個參數?windows

2.java存在這樣的問題該怎麼解決?安全

答:eclipse

1.本人使用的環境以下:編程語言


 

jdk1.6 + windows7 旗艦版ide

通過個人測試,我發現java的方法參數在超過254個時便會報錯函數


2.在這裏我引用 一個名叫 王村平 的文章來處理此類問題:性能

我認爲構造函數和方法過長的傳遞參數列表是一種紅色警告(」red flag「)。在開發過程當中,從邏輯的和功能的角度來看並不是錯誤,可是一般意味着如今或者未來犯錯誤的可能性更高。經過閱讀一系列文章,我發現一些解決參數列表過長的辦法,或者至少這些辦法能夠減小參數個數、加強代碼的可讀性並下降發生錯誤的機率。任何解決問題的辦法都具備優勢和缺點。本文旨在經過使用自定義類型改進長參數方法和構造函數代碼的可讀性和安全性。


方法和構造函數的參數列表過長會產生一系列的障礙。大量的參數不只使得代碼看起來冗餘,並且使得調用起來會很困難。同時,它又容易致使因疏忽而產生的參數移位(參數類型沒變,可是由於位置改變值卻改變了)。這些錯誤在特定狀況下難以發現。幸運地是大多時候咱們沒必要處理另外一個參數過長的缺點:Java虛擬機(JVM)經過編譯時報告錯誤(compile-time error)限制了方法的參數數量。


使用自定義類型一方面能夠減小構造函數和方法的傳參個數,另外一方面又能夠加強參數列表的可讀性而且下降參數位置放錯的可能性。自定義類型的實現方式包括Data Transfer Objects、JavaBeans、Value Objects、Reference Objects或者其餘(在Java中經典的實現方式:類和枚舉)自定義類型。


下面來看一個例子,該方法包含多個String和boolean類型參數:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

   * Instantiate a Person object.

   *

   * @param  lastName

   * @param  firstName

   * @param  middleName

   * @param  salutation

   * @param  suffix

   * @param streetAddress

   * @param city

   * @param state

   * @param isFemale

   * @param isEmployed

   * @param isHomeOwner

   * @return

   */

  public Person createPerson(

     final String lastName,

     final String firstName,

     final String middleName,

     final String salutation,

     final String suffix,

     final String streetAddress,

     final String city,

     final String state,

     final boolean isFemale,

     final boolean isEmployed,

     final boolean isHomeOwner)

  {

     // implementation goes here

  }

能夠發現很容易搞混參數的順序,而後把它們放錯位置。我一般更樂意經過改變參數類型來作一些提升,以期減小參數個數。下面這些代碼展現瞭如何使用自定義類型。

三個名字能夠改成自定義類型Name,而不是使用String。

Name.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

package dustin.examples;

 

/**

 * Name representation.

 *

 * @author Dustin

 */

public final class Name

{

   private final String name;

 

   public Name(final String newName)

   {

      this.name = newName;

   }

 

   public String getName()

   {

      return this.name;

   }

 

   @Override

   public String toString()

   {

      return this.name;

   }

}

稱呼和後綴也能夠替換爲以下兩段代碼所示的自定義類型:

Salutation.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

package dustin.examples;

 

/**

 * Salutations for individuals' names.

 *

 * @author Dustin

 */

public enum Salutation

{

   DR,

   MADAM,

   MISS,

   MR,

   MRS,

   MS,

   SIR

}

Suffix.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

package dustin.examples;

 

/**

 * Suffix representation.

 *

 * @author Dustin

 */

public enum Suffix

{

   III,

   IV,

   JR,

   SR

}

其餘的代碼也可以使用自定義類型。下面經過枚舉的方式替換boolean型,以提升代碼的可讀性:

Gender.java

1

2

3

4

5

6

7

8

9

10

11

12

package dustin.examples;

 

/**

 * Gender representation.

 *

 * @author Dustin

 */

public enum Gender

{

   FEMALE,

   MALE

}

EmploymentStatus.java

1

2

3

4

5

6

7

8

9

10

11

12

package dustin.examples;

 

/**

 * Representation of employment status.

 *

 * @author Dustin

 */

public enum EmploymentStatus

{

   EMPLOYED,

   NOT_EMPLOYED

}

HomeOwnerStatus.java

1

2

3

4

5

6

7

8

9

10

11

12

package dustin.examples;

 

/**

 * Representation of homeowner status.

 *

 * @author Dustin

 */

public enum HomeownerStatus

{

   HOME_OWNER,

   RENTER

}

此人的地址信息能夠經過以下代碼所示的自定義類型做爲參數進行傳遞。
StreetAddress.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

package dustin.examples;

 

/**

 * Street Address representation.

 *

 * @author Dustin

 */

public final class StreetAddress

{

   private final String address;

 

   public StreetAddress(final String newStreetAddress)

   {

      this.address = newStreetAddress;

   }

 

   public String getAddress()

   {

      return this.address;

   }

 

   @Override

   public String toString()

   {

      return this.address;

   }

}

City.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

package dustin.examples;

 

/**

 * City representation.

 *

 * @author Dustin

 */

public final class City

{

   private final String cityName;

 

   public City(final String newCityName)

   {

      this.cityName = newCityName;

   }

 

   public String getCityName()

   {

      return this.cityName;

   }

 

   @Override

   public String toString()

   {

      return this.cityName;

   }

}

State.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

package dustin.examples;

 

/**

 * Simple representation of a state in the United States.

 *

 * @author Dustin

 */

public enum State

{

   AK,

   AL,

   AR,

   AZ,

   CA,

   CO,

   CT,

   DE,

   FL,

   GA,

   HI,

   IA,

   ID,

   IL,

   IN,

   KS,

   KY,

   LA,

   MA,

   MD,

   ME,

   MI,

   MN,

   MO,

   MS,

   MT,

   NC,

   ND,

   NE,

   NH,

   NJ,

   NM,

   NV,

   NY,

   OH,

   OK,

   OR,

   PA,

   RI,

   SC,

   SD,

   TN,

   TX,

   UT,

   VA,

   VT,

   WA,

   WI,

   WV,

   WY

}

經過使用自定義類型,開始展現的方法的代碼變得更加易讀易懂,同時更不容易出錯了。下面是使用自定義類型改寫後的方法:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

public Person createPerson(

   final Name lastName,

   final Name firstName,

   final Name middleName,

   final Salutation salutation,

   final Suffix suffix,

   final StreetAddress address,

   final City city,

   final State state,

   final Gender gender,

   final EmploymentStatus employment,

   final HomeownerStatus homeowner)

{

   // implementation goes here

}

在上面這段代碼中,編譯器會不容許使用先前那種不少String、boolean參數的方式。這樣來減小了放錯參數順序的可能性,從而幫助到開發者。可是三個名字仍然存在一個潛在的問題,由於代碼的調用者依然容易搞亂它們的順序。出於這種擔憂,須要爲此專門定義FirstName、LastName、MiddleName 三種類型。但一般我喜歡使用一個自定義類型,裏面放置上述三個名字做爲新類的屬性。固然那屬於後來即將講解的解決Java參數過長問題的文章的內容了。

使用自定義類型的好處和優勢


提升了代碼的可讀性,爲代碼的維護者和API調用者提供了便利。提升了在編寫代碼時開發環境(IDE)參數匹配的能力,沒有什麼比使用自定義類型的編譯環境檢查更能幫助開發環境的了。一般來講,我更喜歡儘量地把這些自動檢查由運行環境移到編譯環境,而且把他們定義爲可直接調用的靜態類型而非普通類型。

進一步說,自定義類型的存在也使咱們未來爲它添加更多細節變得更加容易。例如:未來我也許會爲方法建立人添加一個全名或者把其餘的狀態放在枚舉器當中,同時這樣也不會改變自定義類型的原有面貌。這些都是使用String類型沒法完成的。這樣作的另外一個潛在優勢就是使用自定義類型擁有更大的靈活性,能夠在不改變原有類型面貌的狀況下改變實現方式。這些自定義類型(不包括枚舉器)可以被擴展(String則不具有),而且能夠在不改變它的類型的狀況下靈活添加自定義細節。

自定義類型的代價和缺點

廣泛存在缺點之一,就是開始須要額外的實例化和佔用內存。例如:Name類須要實例化,並且封裝了String。我認爲之因此有人會持有這種觀點,更多的是由於他從一種尚不夠成熟的所謂的最優化角度,而非實用合理的角度來衡量性能問題。固然也有這種狀況存在,即:額外實例化這些類型花費了太多的代價而且不能證實加強可讀性和編譯能力所帶來的好處。然而大多時候這種額外的開銷都是能夠承受的,不會產生什麼可見的壞影響。若是大多數時候使用自定義類型而不用String或者boolean會產生性能問題,這真的讓人難以置信。
另外一些人認爲使用自定義類型而非內置類型須要付出額外的寫和測試代碼的努力。然而,正如個人這篇文章的代碼所顯示的那樣,這些很是簡單的類和枚舉器寫和測試起來並不難。使用一個優秀的開發環境和一門靈活的編程語言(如:Groovy),編寫和測試會更加容易並且一般能夠自動完成。

結論

我喜歡使用自定義類型來提升代碼的可讀性,將更多的編譯檢查負擔轉給編譯器。我不喜歡這種傳參方式的最大緣由在於:這種方法自己只是提升了擁有過長參數列表的構造函數和方法的可讀性卻並無減小實際須要傳遞的參數數量,代碼的調用者依然須要寫那些笨拙的客戶端代碼來調用構造函數和方法。所以,我一般使用其它技術而不是增長自定義類型來解決向方法傳遞參數過長的問題。這些技術將在接下來的文章裏講述。

相關文章
相關標籤/搜索