2009-12-27 110 views
70

爲什麼我們有一個數組的長度作爲屬性,array.length,併爲字符串我們有一個方法,str.length()長度和長度()在Java

有什麼理由嗎?

+3

已經在CodeRanch討論過了。參見討論[這裏](http://www.coderanch.com/t/383558/Java-General/java/String-length-vs-Arrays-length) – missingfaktor 2009-12-27 08:39:54

回答

23

有點簡化,你可以把它看作是一個特殊情況的數組,而不是普通的類(有點像基元,但不是)。字符串和所有集合都是類,因此是獲取大小,長度或類似事物的方法。

我想當時設計的原因是性能。如果他們今天創建了它們,他們可能會想出類似於數組支持的集合類。

如果有人有興趣,這裏是一個很小的代碼片段闡述了兩者之間的差異所產生的代碼,第一個來源:

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

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()),而在th e字符串大小寫(28-35)它需要做一個方法調用來獲取長度。

在20世紀90年代中期,如果沒有良好的JIT和東西,它會完全殺死性能,只有java.util.Vector(或類似的東西),而不是一個語言結構,它並不像一個類,很快。他們當然可以將該屬性掩蓋爲方法調用並在編譯器中處理它,但我認爲如果對某個不是真正的類的方法有一個方法會更困難。

+1

Java將數組視爲對象和字符串作爲不可變對象! :| – 2009-12-27 08:33:56

+0

@Myth:我看不到你的觀點......數組的長度屬性不是公共字段或任何東西,它是jvm的一個構造(arraylength甚至是字節碼中的一個操作)。當您執行JNI時,或者您只是反彙編代碼時,這一點非常明顯。 – Fredrik 2009-12-27 08:39:53

2

在Java中,數組將其長度與實際保存數據的結構分開存儲。當你創建一個數組時,你可以指定它的長度,並且它將成爲數組的一個定義屬性。不管你對一個長度爲N的數組做什麼(改變數值,空值等),它總是一個長度爲N的數組。

一個字符串的長度是偶然的;它不是字符串的屬性,而是副產品。儘管Java字符串實際上是不可變的,但如果可以更改其內容,則可以更改它們的長度。敲掉最後一個字符(如果可能的話)會降低長度。

我知道這是一個很好的區別,我可能會被拒絕,但它是真的。如果我創建一個長度爲4的數組,那麼這四個長度是數組的一個定義特徵,並且無論內部是什麼都是真實的。如果我創建一個包含「狗」的字符串,該字符串長度爲4,因爲它恰好包含四個字符。

我認爲這是做一個具有屬性而另一個具有方法的理由。事實上,這可能只是一個無意的不一致性,但對我來說總是有意義的,而且我總是這樣想。

1

我被教導說,對於數組而言,由於以下恐懼,通過方法不會檢索長度:程序員只會在進入循環之前將長度分配給局部變量(考慮for循環的條件使用數組的長度)程序員應該這樣做,以減少函數調用(從而提高性能)。問題是在循環期間長度可能會改變,而變量不會。

+0

好點..... – Zaki 2009-12-27 08:41:52

+10

在循環中數組的長度不能改變。 – Fredrik 2009-12-27 09:02:40

+2

你不能改變這個特定數組的長度,但是你可以給同一個變量分配一個新的 – Bozho 2009-12-27 09:32:19

5

考慮:

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 

這很可能是字符串和數組被設計在不同的時間,從而結束了使用不同的約定。其中一個理由是,由於字符串在內部使用數組,所以使用方法length()來避免重複相同的信息。另一種方法是使用方法length()有助於強調字符串的不變性,即使數組的大小也不可更改。

最終,這只是一個不一致的情況,如果語言是從頭開始重新設計的話,那麼這種不一致將會得到解決。據我所知,沒有其他語言(C#,Python,Scala等)做同樣的事情,所以這可能只是作爲語言一部分的一個小缺陷。

無論如何,如果您使用錯誤的話,您將會收到錯誤信息。

+0

這是更合理和公正的答案。 – 2017-12-12 00:06:09

72

讓我先突出三種不同的方式來達到類似的目的。

length - 陣列int[]double[]String[]) - 知道數組的長度

length() - 字符串對象相關StringStringBuilder等) - 知道字符串長度

size() - 收集對象ArrayList,Set,等等) - 要知道收集的大小

現在忘記length()只考慮lengthsize()

length不是一種方法,所以完全有意義的是,它不會在對象上工作。它只適用於數組。
size()它的名字更好地描述了它,因爲它是一種方法,它將用於那些使用集合(集合框架)的對象,就像我在那裏說的那樣。

現在來length()
字符串不是原始陣列(所以我們不能用.length),也沒有一個集合(所以我們不能用.size()),這就是爲什麼我們還需要一個不同的是length()(保持差異並達到目的)。

作爲回答爲什麼?
我覺得它很有用,易於記憶和使用,並且友好。

+2

真棒解決方案! – 2017-04-30 14:58:00

6

.length是Java的一次性屬性。它用於查找單維陣列的尺寸

.length()是一種方法。它用於查找長度爲String。它避免了重複的價值。

-1

我只是想通過Fredrik向偉大的answer添加一些評論。

Java Language Specification in Section 4.3.1的狀態

一種對象類實例陣列

所以數組在Java中的確有着非常特殊的作用。我想知道爲什麼。

有人可能會爭辯說,當前的實現數組對於更好的性能很重要。但比它是一個內部結構,不應該暴露。

他們當然可以將屬性掩蓋爲方法調用並在編譯器中處理它,但我認爲如果對某個非真實類的東西有方法會更困惑。

我同意弗雷德裏克,一個聰明的編譯器優化將是更好的選擇。這也可以解決問題,即使對數組使用屬性,也沒有解決字符串和其他(不可變)集合類型的問題,因爲例如string基於char數組,因爲您可以在的String類定義:

public final class String implements java.io.Serializable, Comparable<String>, CharSequence {   
    private final char value[]; // ... 

而且我不認爲它會變得更加令人困惑同意,因爲數組沒有繼承all methods from java.lang.Object

作爲一名工程師,我真的不喜歡答案「因爲它一直這樣。」並希望會有更好的答案。但在這種情況下,似乎是這樣。

TL;博士

在我看來,這是Java的設計缺陷,不應該有這種方式來實現。