web-dev-qa-db-ja.com

Javaのlengthおよびlength()

配列の長さを属性として持つのはarray.lengthで、Stringの場合はメソッドとしてstr.length()があるのですか?

なんらかの理由がありますか?

84
Nitish Upreti

少し簡略化すると、通常のクラスではなく、特殊なケースである配列と考えることができます(プリミティブに少し似ていますが、そうではありません)。文字列とすべてのコレクションはクラスであるため、サイズ、長さなどを取得するメソッドです。

設計時の理由はパフォーマンスだったと思います。彼らが今日それを作成した場合、彼らはおそらく配列に裏付けされたコレクションクラスのようなものを代わりに思いついたでしょう。

誰かが興味を持っているなら、ここに生成されたコードの最初の2つの違いを説明するための小さなコードスニペットがあります。

public class LengthTest {
  public static void main(String[] args) {
    int[] array = {12,1,4};
    String string = "Hoo";
    System.out.println(array.length);
    System.out.println(string.length());
  }
}

クラスでjavap -cを実行して、バイトコードのそれほど重要ではない部分を切り取ると、最後の2行について次のようになります。

20: getstatic   #3; //Field Java/lang/System.out:Ljava/io/PrintStream;
23: aload_1
24: arraylength
25: invokevirtual   #4; //Method Java/io/PrintStream.println:(I)V
28: getstatic   #3; //Field Java/lang/System.out:Ljava/io/PrintStream;
31: aload_2
32: invokevirtual   #5; //Method Java/lang/String.length:()I
35: invokevirtual   #4; //Method Java/io/PrintStream.println:(I)V

最初のケース(20-25)では、コードはJVMに配列のサイズを要求します(JNIではGetArrayLength()の呼び出しでした)が、Stringの場合(28-35)では、長さを取得するメソッド呼び出し。

1990年代半ばには、優れたJITなどがなければ、Java.util.Vector(または同様のもの)のみを持ち、実際にはクラスのように振る舞わなかったが高速な言語コンストラクトがないと、パフォーマンスが完全に低下していました。もちろん、プロパティをメソッド呼び出しとしてマスクし、コンパイラで処理することもできますが、実際のクラスではないものにメソッドを設定することはさらに混乱したと思います。

25
Fredrik

考慮してください:

int[] myArray = new int[10];
String myString = "hello world!";
List<int> myList = new ArrayList<int>();

myArray.length    // Gives the length of the array
myString.length() // Gives the length of the string
myList.size()     // Gives the length of the list

文字列と配列は異なる時間に設計されたため、異なる規則を使用することになりました。 1つの正当化は、文字列は内部的に配列を使用するため、同じ情報の重複を避けるためにメソッドlength()が使用されたということです。もう1つは、メソッドlength()を使用すると、配列のサイズも変更できない場合でも、文字列の不変性を強調するのに役立ちます。

最終的に、これは進化した不整合であり、言語がゼロから再設計された場合に確実に修正されます。私が知る限り、他の言語(C#、Python、Scalaなど)が同じことを行うことはないため、これは言語の一部として最終的にはわずかな欠陥である可能性があります。

とにかく間違ったものを使用すると、エラーが発生します。

7

.lengthは、Javaの一時的なプロパティです。単次元配列のサイズを見つけるために使用されます。

.length()はメソッドです。 Stringの長さを見つけるために使用されます。値の重複を避けます。

7
Prabandha

Javaでは、配列はその長さを、実際にデータを保持する構造とは別に保存します。配列を作成するとき、その長さを指定し、それが配列の定義属性になります。長さNの配列に対して何をしても(値の変更、nullの出力など)、それは常に長さNの配列になります。

ストリングの長さは偶発的です。これは文字列の属性ではなく、副産物です。 Java文字列は実際には不変ですが、内容を変更できる場合は、長さを変更できます。最後の文字をノックオフすると(可能な場合)、長さが短くなります。

私はこれが素晴らしい区別であることを理解しており、それに対して賛成票を投じられるかもしれませんが、それは本当です。長さ4の配列を作成する場合、その4つの長さは配列の定義特性であり、何が保持されているかに関係なく真実です。 「犬」を含むストリングを作成すると、たまたま4文字含まれているため、そのストリングの長さは4です。

これは、属性を使用して1つを実行し、メソッドを使用してもう1つを実行する正当な理由と考えています。事実、それは単なる意図しない矛盾かもしれませんが、それは常に私にとって理にかなっており、これは常に私がそれについて考えた方法です。

2
jakeboxer

配列の場合、長さはメソッドを介して取得されないという教訓がありました:プログラマーは、ループに入る前にローカル変数に長さを割り当てるだけです(条件付きで配列の長さを使用するforループを考えてください)。おそらく関数呼び出しを減らすためにそうするでしょう(そしてそれによってパフォーマンスを改善します。)問題はループの間に長さが変わるかもしれず、変数はそうではないということです。

1
Matthew

配列が作成されるたびに、そのサイズが指定されます。したがって、長さは構築属性と見なすことができます。 Stringの場合、本質的にはchar配列です。長さは、char配列のプロパティです。すべてがこのフィールドを必要とするわけではないため、長さをフィールドとして指定する必要はありません。 http://www.programcreek.com/2013/11/start-from-length-length-in-Java/

0
Ryan