簡體   English   中英

具有可變參數參數的多個構造函數

[英]Multiple constructors with variable argument parameters

給定這兩個構造函數:

SomeClass(int... params)
{
   // Do things
}

SomeClass(long... otherParams)
{
   // Do other things
}

實例化對象foo會發生什么?

SomeClass foo = new SomeClass();

未定義的默認構造函數是否以某種方式被調用? 還是那些名為空數組的構造函數之一? 如果是這樣,先例是什么?

我已經做了一些基本的測試,發現如果定義了一個沒有參數的構造函數,那么它將被調用。 否則, 似乎被稱為模棱兩可的。

按照下面的“ Java方法重載中的變量”中的一個很好的答案,問題是Java編譯器用於選擇要調用的方法簽名的規則。 它們基於JLS 5.3。 方法調用轉換文檔。

  1. 基本擴展使用可能的最小方法參數
  2. 包裝器類型無法擴展為其他包裝器類型
  3. 您可以將Box從int更改為Integer,然后將其擴展為Object但不能將其擴展為Long
  4. 加寬節拍,搏擊節拍可變參數。
  5. 您可以先裝箱然后加寬(一個int可以通過Integer變成Object
  6. 您不能加寬,然后Box(一個int不能變Long
  7. 您不能將var-args與擴大或裝箱結合使用

由於兩個構造函數都是var-args(規則7),因此編譯器將退回到其他規則,並選擇使用最小類型的方法(規則1)。

您可以使用以下代碼確認此行為:

static class SomeClass {
  SomeClass(long... value) { System.out.println("Long"); }
  SomeClass(int... value) { System.out.println("Int"); }
  SomeClass(byte... value) { System.out.println("Byte"); }
}

public static void main(String[] args) throws Exception {
  SomeClass o = new SomeClass(); // Byte
}

JLS 4.10.1中解釋了規則1中使用的基本類型之間的精確子類型關系 基本類型之間的子類型化

以下規則定義了原始類型之間的直接超類型關系:

  • 雙> 1浮點

  • 浮動> 1

  • long> 1個整數

  • 整數> 1個字符

  • int> 1

  • 短> 1個字節

只有根本沒有任何顯式構造函數的類才獲得默認構造函數。 對於確實具有一個或多個明確定義的構造函數的類,其Arity(無論變量與否)都不起作用。 因此,一個類沒有null構造函數是很常見的,實際上就是您的類的情況。

從多個可用的構造函數中進行選擇的方式與在重載方法中進行選擇的方式相同。 首先,確定可用的構造函數。 然后,確定適用於給定參數的參數。 最后,在適用的構造函數中選擇最具體的。 詳細信息在JLS10的15.12節中指定。 如果該過程沒有導致確切地標識一個構造函數,則將導致編譯時錯誤。

在您的示例中,兩個可用的構造函數均適用於空參數列表,因此歸結為選擇最具體的問題。 JLS提供了一個非正式的描述:

如果第一種方法處理的任何調用都可以傳遞給另一個方法而沒有編譯時錯誤,則一個方法比另一個方法更具體。

形式規則圍繞形式參數的類型展開,並說明原始類型之間的形式類型/子類型關系,最終結果是,當兩者都SomeClass(long...)SomeClass(int...)SomeClass(long...)更具體SomeClass(long...)適用。 那么,前者就是您的示例中選擇的那個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM