首頁 > 軟體

java 定義長度為0的陣列/空陣列案例

2021-03-25 13:01:23

如下:

int[] array = new int[0];   // 定義一個長度為 0 的陣列 / 空陣列
Sring[] arr = new String[0]; // 定義一個長度為 0 的陣列 / 空陣列

長度為 0 的陣列 / 空陣列 並不是 null

有時陣列裡可能只有一個空字串 "",這時陣列長度是 1。這種情況也要注意判斷。

if ( arr.length == 1 && arr[ 0 ].equals( "" ) ) {
  System.out.println( "輸入的陣列不能只包含一個空字串" );
  return;
}

補充:java定義一個空陣列_一個 Java 方法,最多能定義多少引數?

在 JVM 中,一個 Java 方法,最多能定義多少引數呢?這是一個很無聊的問題,即使能定義一萬個,十萬個,誰又會真的去這麼做呢。

但是作為一個 coder,最重要的不就是好奇心嗎,沒有好奇心,和一條鹹魚又有什麼區別呢?本文作者就是這樣一位充滿好奇心的 coder。

我最近給我的 QuickTheories 分支新增了一個介面:

@FunctionalInterface
public interface QuadFunction {
  E apply(A a, B b, C c, D d);
}

讓我好奇的是這個方法能有多少個型別引數。到目前為止,我敢說,Java 語言規範並沒有談及這個問題。

對於實現定義的限制可能是什麼,我有兩個猜測:

1、編譯器會設定一個可預測的限制,如 255 或 65535。

2、編譯器的緊急行為會由於實現細節(堆疊溢位或同樣不可預測/不相關的東西)而設定意外的限制。

我不想在原始碼上測試我那點可憐的 C++技巧,所以我決定只測試編譯器做了什麼。我寫了一個 Python 指令碼,它使用二進位制搜尋找到最少的致錯型別引數。完整的指令碼放在 Github repo (https://github.com/hyperpape/java-max-type-params) 中。

指令碼地址:https://github.com/hyperpape/java-max-type-params

生成方法很簡單。幸運的是,我們不必使用任何型別引數,只需以的形式發出它們:

def write_type_plain(count):
  with open('Test.java', 'w') as f:
    f.write("public class Test {n")
    f.write("public     for i in range(count):
      if (i > 0):
        f.write(", ")
      f.write("A" + str(i + 1))
    f.write("> void testMethod() {}")
    f.write("}")

執行二進位制搜尋可以得到以下輸出:

>>> error: UTF8 representation for string ">>> largest type: 2776

這個錯誤有點模糊,但事後看來是可以預見的。編譯器生成的類檔案包含許多字串,包括類中每個方法的方法簽名。這些字串儲存在常數池中,常數池中的條目最大為 65535 位元組,這是由 JVM 規範規定的限制。

所以,我之前的猜測都不完全正確。型別引數的最大數目是一個突現特徵(emergent property),而不是一個明確的決定。不過,並不是編譯器本身的實現導致了錯誤。

相反,JVM 的類檔案格式限制了可以在類檔案中表示的型別引數的數量。這是真的,儘管 JVM對泛型一無所知。這也意味著型別引數的最大數目完全取決於如何編寫方法。

我嘗試了一種新的編碼型別引數的方法(先前連結檔案中的 write_Type_Compact),使用完整的合法 ASCII 字元(A-Z、a-z、$和_)。該實現有點過於複雜,因為可以使用字元 0~9,但不能是識別符號的初始字元,因為 Java 關鍵字不能作為型別引數出現。我只是用等長的 UTF-8 字元替換了短單詞「if」和「do」。更緊湊的編碼將引數數量從 2776 增加到 3123。

不方便的是,_A 是一種合法的 Java 識別符號,但 _ 不是。謝天謝地,我的編碼在不使用初始_情況下就生成了 3392 個 2 位元組型別引數,因此我覺得沒有必要進行簿記以發出初始字元_。

再來一個小技巧

解壓類檔案顯示,65536 個字元的大部分不是我生成的型別引數,而是子字串 Ljava/lang/object 的重複範例。因為沒有提供關於型別引數的資訊,所以類檔案顯示它們擴充套件了物件,並在方法簽名中對其進行編碼。我修改了生成器來解決這個問題。

迴圈的關鍵部分是:

s = type_var(i)
f.write(s)
if (s != 'A'):
  f.write(" extends A")

在型別引數中,除了一個範例 java/Lang/Object 之外的所有範例都被替換為 A。在進行了這個更改之後,編譯了一個具有 9851 個型別引數的方法。

由於引數的數量增加了很多,所以我使用的程式碼肯定需要調整。使用非 ASCII Unicode 識別符號可能是完全高效的必要條件,但簡單地指出這是可以做到的我就很滿意了。

這些都不重要

很難想象有人會達到這個極限。程式碼生成有時會達到語言或編譯器的限制,但即使生成的程式碼似乎也不太可能使用成百上千的型別引數。

儘管如此,如果我是規則制定者,我會考慮明確禁止任何類或方法具有 255 個以上的型別引數。明確的限制似乎更好,即使它隻影響百萬分之一的程式。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。如有錯誤或未考慮完全的地方,望不吝賜教。


IT145.com E-mail:sddin#qq.com