uzunluk ve uzunluk () Java'da


88

Neden öznitelik olarak bir dizinin uzunluğuna sahibiz array.lengthve String için bir yöntemimiz var str.length()?

Bir sebep var mı


3
CodeRanch'da daha önce tartışılmıştı. Tartışmaya buradan
missingfaktor

Yanıtlar:


98

Önce benzer amaç için üç farklı yolu vurgulayayım.

length- diziler ( int[], double[], String[]) - dizilerin uzunluğu bilmek

length()- Dizeyle ilgili Nesne ( String, StringBuildervb.) - Dizenin uzunluğunu bilmek için

size()- Koleksiyon Nesnesi ( ArrayList, Setvb.) - Koleksiyonun boyutunu bilmek için

Şimdi length()sadece lengthve düşünmeyi unutun size().

lengthbir yöntem değildir, bu nedenle nesneler üzerinde çalışmayacağı tamamen mantıklıdır. Yalnızca diziler üzerinde çalışır.
size()adı onu daha iyi anlatıyor ve bir yöntem olduğu için yukarıda da söylediğim gibi koleksiyonla (koleksiyon çerçeveleri) çalışan nesnelerde kullanılacak.

Şimdi gelin length():
String bir ilkel dizi değil (bu yüzden kullanamayız .length) ve ayrıca bir Koleksiyon değil (bu yüzden kullanamayız .size()) bu yüzden farklı bir diziye ihtiyacımız var length()(farklılıkları koruyun ve amaca hizmet edin).

Neden cevabı olarak ?
Kullanışlı, hatırlaması ve kullanması kolay ve arkadaşça buluyorum.


6
harika çözüm!
Jeff Hu

27

Biraz basitleştirildiğinde, dizilerin sıradan sınıflar değil özel bir durum olduğunu düşünebilirsiniz (biraz ilkellere benziyor, ama değil). String ve tüm koleksiyonlar sınıflardır, dolayısıyla boyut, uzunluk veya benzer şeyler elde etme yöntemleri.

Sanırım tasarımın yapıldığı sıradaki sebep performanstı. Bugün yarattılarsa, bunun yerine muhtemelen dizi tabanlı koleksiyon sınıfları gibi bir şey bulmuşlardı.

İlgilenen varsa, oluşturulan koddaki ikisi arasındaki farkı göstermek için küçük bir kod parçacığı, önce kaynak:

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());
  }
}

Bayt kodunun o kadar önemli olmayan kısmını bir şekilde kesmek javap -c, sınıfta çalışmak son iki satır için aşağıdakilere neden olur:

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

İlk durumda (20-25) kod, JVM'den dizinin boyutunu sorar (JNI'de bu, GetArrayLength () için bir çağrı olurdu), oysa String durumunda (28-35) bir uzunluğu almak için yöntem çağrısı.

1990'ların ortalarında, iyi JIT'ler ve benzeri şeyler olmadan, yalnızca java.util.Vector'a (veya benzer bir şeye) sahip olmak ve gerçekten bir sınıf gibi davranmayan ancak hızlı olan bir dil yapısına sahip olmak performansı tamamen öldürecekti. Elbette özelliği bir yöntem çağrısı olarak maskeleyip derleyicide ele alabilirlerdi, ancak gerçek bir sınıf olmayan bir şey üzerinde bir yönteme sahip olmanın daha da kafa karıştırıcı olacağını düşünüyorum.


1
Java diziyi nesneler ve dizgeleri değişmez nesneler olarak ele alır !! : |
Nitish Upreti

@Myth: Amacınızı göremiyorum ... Dizilerin length özelliği genel bir alan veya herhangi bir şey değil, jvm'nin bir yapısıdır (dizi uzunluğu bayt kodundaki bir işlemdir). JNI yaptığınızda veya kodu geldiği yerde parçalara ayırdığınızda çok açıktır.
Fredrik

Özgün tasarımın gerekçesinin sadece performans olduğunu düşünmüyorum. VectorJava dilinin dizi desteği olmadığında nasıl uygularsınız ?
Holger

8

.lengthbir kereye mahsus bir Java özelliğidir. Tek boyutlu bir dizinin boyutunu bulmak için kullanılır .

.length()bir yöntemdir. A'nın uzunluğunu bulmak için kullanılır String. Değerin kopyalanmasını önler.


8

Düşünmek:

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

Dizelerin ve dizilerin farklı zamanlarda tasarlanması ve dolayısıyla farklı kurallar kullanılarak sonuçlanması çok muhtemeldir. Bunun bir gerekçesi, Dizeler dizileri dahili length()olarak kullandığından, aynı bilgilerin tekrarlanmasını önlemek için bir yöntemin kullanılmasıdır. Bir diğeri, length()bir dizinin boyutu da değiştirilemez olsa da, bir yöntem kullanmak dizelerin değişmezliğini vurgulamaya yardımcı olmasıdır.

Nihayetinde, bu sadece, eğer dil sıfırdan yeniden tasarlandıysa kesinlikle düzeltilecek bir tutarsızlıktır. Başka hiçbir dilin (C #, Python, Scala, vb.) Aynı şeyi yapmadığını bilmediğim kadarıyla, bu muhtemelen dilin bir parçası olarak ortaya çıkan küçük bir kusurdur.

Yine de yanlış olanı kullanırsanız bir hata alırsınız.


Bu daha haklı ve tarafsız bir cevaptır.
Zubair Alam

3

Java'da bir Dizi, uzunluğunu verileri gerçekten tutan yapıdan ayrı olarak depolar. Bir Dizi oluşturduğunuzda, uzunluğunu belirtirsiniz ve bu, Dizinin tanımlayıcı bir niteliği haline gelir. N uzunluktaki bir Diziye ne yaparsanız yapın (değerleri değiştirin, sıfır şeyler, vb.), Her zaman N uzunluğunda bir Dizi olacaktır.

Bir String'in uzunluğu arızi; bu, String'in bir özelliği değil, bir yan üründür. Java Strings aslında değişmez olsa da, içeriklerini değiştirmek mümkün olsaydı uzunluklarını değiştirebilirsiniz. Son karakteri düşürmek (mümkün olsaydı) uzunluğu azaltırdı.

Bunun ince bir ayrım olduğunu anlıyorum ve buna oy verilebilirim, ama bu doğru. Uzunluğu 4 olan bir Dizi yaparsam, bu dört uzunluğu Array'in tanımlayıcı bir özelliğidir ve içinde ne tutulduğuna bakılmaksızın doğrudur. "Köpekler" içeren bir Dize yaparsam, bu Dize 4 karakterdir çünkü dört karakter içerir.

Bunu, birini bir öznitelikle, diğerini bir yöntemle yapmanın gerekçesi olarak görüyorum. Gerçekte, bu sadece kasıtsız bir tutarsızlık olabilir, ama bana her zaman mantıklı geldi ve ben de hep böyle düşündüm.


2

Diziler için uzunluğun şu korkudan dolayı bir yöntemle alınmadığı öğretildi: programcılar bir döngüye girmeden önce uzunluğu yerel bir değişkene atarlar (koşulun dizinin uzunluğunu kullandığı bir for döngüsü düşünün). işlev çağrılarını azaltmak (ve böylece performansı artırmak) için sözde bunu yapacaktı. Sorun, uzunluğun döngü sırasında değişebileceği ve değişkenin değişmeyeceğidir.


10
Bir dizinin uzunluğu döngü sırasında değişemez.
Fredrik

2
bu dizinin uzunluğunu değiştiremezsiniz, ancak aynı değişkene yeni bir tane atayabilirsiniz
Bozho

2
@Bozho: Doğru, ama o zaman başka bir dizi ve bunu kasıtlı olarak yaparsanız ve döngünüzü kontrol ettiğiniz her şeyi güncellemezseniz bir hatanız olur. Java, hiçbir zaman sizi hata yazmaktan alıkoyma niyetinde olmadı. Java sizi engellemeye çalışmadan sonsuz döngüler, ölene kadar özyineleme ve her türlü mantıksal hatayı yapabilirsiniz. Uzunluğu bir değişkende saklamamak için iyi bir neden ama kesinlikle bu şekilde tasarlanmasının nedeni bu değil.
Fredrik


0

Sadece harika bazı açıklamalar eklemek istediğiniz cevap tarafından Fredrik .

4.3.1 Bölüm Java Dil Şartname devletler

Bir nesne , bir sınıf örneği veya bir dizidir .

Yani dizi gerçekten Java'da çok özel bir role sahiptir. Nedenini merak ediyorum.

Mevcut uygulama dizisinin daha iyi bir performans için önemli olduğu / önemli olduğu tartışılabilir. Ama daha çok açığa çıkarılmaması gereken bir iç yapıdır.

Elbette özelliği bir yöntem çağrısı olarak maskeleyip derleyicide ele alabilirlerdi, ancak gerçek bir sınıf olmayan bir şey üzerinde bir yönteme sahip olmanın daha da kafa karıştırıcı olacağını düşünüyorum.

Akıllı bir derleyici optimizasyonunun daha iyi bir seçim olacağı konusunda Fredrik'e katılıyorum. Bu aynı zamanda, diziler için bir özellik kullansanız bile, dizeler ve diğer (değişmez) koleksiyon türleri için problemi çözmemiş olmanız sorununu çözecektir, çünkü, örneğin, sınıf tanımında görebileceğiniz gibi stringbir chardiziye dayanmaktadır. arasında String:

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

Ve bunun daha da kafa karıştırıcı olacağına katılmıyorum çünkü dizi tüm yöntemlerijava.lang.Object miras alıyor .

Bir mühendis olarak "Çünkü her zaman böyleydi" cevabını gerçekten beğenmiyorum. ve daha iyi bir cevap olmasını diledi. Ama bu durumda öyle görünüyor.

tl; dr

Bence Java'nın bir tasarım hatası ve bu şekilde uygulanmamalıydı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.