Java API neden kısa veya bayt yerine int kullanıyor?


Yanıtlar:


167

Bazı nedenler zaten belirtildi. Örneğin, "... (Neredeyse) Bayt üzerindeki tüm işlemler kısa, bu ilkelleri int'e teşvik edecektir" . Ancak, bariz bir sonraki soru olacaktır: NEDEN bu tür terfi int?

Bu nedenle, bir seviye daha derine inmek için: Yanıt sadece Java Sanal Makine Komut Seti ile ilgili olabilir. Özetlendiği gibi Java Virtual Machine Şartnamede Tablo , tüm ayrılmaz aritmetik işlemler, ekleme, bölme ve diğerleri gibi, sadece türü için kullanılabilir intve tip longve olmayan küçük türleri için.

(Bir taraf: Daha küçük türler ( byteve short) temel olarak yalnızca diziler için tasarlanmıştır . Benzeri bir dizinew byte[1000] 1000 bayt alır ve benzeri bir dizi new int[1000]4000 bayt alır)

Şimdi, tabii ki, denebilir o "... bariz bir sonraki soru olacaktır: NEDEN bu talimatlar için sunulmaktadır int(ve long)?" .

Bir neden yukarıda belirtilen JVM Spesifikasyonunda belirtilmiştir:

Yazılan her yönerge tüm Java Sanal Makinesi'nin çalışma zamanı veri türlerini destekliyorsa, bir baytta gösterilenden daha fazla yönerge olurdu

Ek olarak, Java Sanal Makinesi gerçek bir işlemcinin bir soyutlaması olarak düşünülebilir. Ve daha küçük tipler için özel Aritmetik Mantık Birimi tanıtmak çabaya değmez: Ek transistörlere ihtiyaç duyacaktır, ancak yine de bir saat döngüsünde sadece bir ekleme yapabilir. JVM tasarlanırken baskın mimari 32 bit, 32bit için doğru int. (64 bit longdeğeri içeren işlemler özel bir durum olarak uygulanır).

(Not: Son paragraf, olası vektörleştirme vb. Göz önüne alındığında biraz fazla basitleştirilmiştir, ancak işlemci tasarım konularına çok derinlemesine dalmadan temel fikri vermelidir)


DÜZENLEME: Sorunun örneğine odaklanan, ancak daha genel anlamda kısa bir zeyilname: Ayrıca , daha küçük türleri kullanarak alanların depolanmasının yararlı olup olmayacağı da sorabilir . Örneğin, bellek Calendar.DAY_OF_WEEKolarak a olarak saklanarak kurtarılabileceği düşünülebilir byte. Ancak burada, Java Sınıfı Dosya Biçimi devreye girer: Bir Sınıf Dosyasındaki Tüm Alanlar , bir int(32 bit) büyüklüğünde en az bir "yuva" kullanır . ("Geniş" alanlar doubleve longiki yuva kaplar). Bu yüzden bir alanı açıkça belirtmek shortveya byteherhangi bir belleği kaydetmemek.



@ Marco13 "Bir alanı kısa veya bayt olarak açıkça belirtmek de hafızayı kurtarmaz." bu doğru mu? Bunun doğru olduğunu düşünmüyorum.
ACV

@ACV Açıkçası, bir uygulama daha kompakt bir form saklamayı seçebilir, ancak "sanal olarak" (yani sanal makine tarafından) ortaya çıkarılan format, değerleri en azından boyutuna sahip olarak değerlendirir int. Başka bir uygulamaya referansınız varsa, yanıtı güncelleyip bağlantıyı buna göre eklerdim.
Marco13

40

(Neredeyse) tüm işlemler byte, shortonları teşvik edecek kadar int, örneğin, yazamıyor:

short x = 1;
short y = 2;

short z = x + y; //error

Aritmetikler kullanırken daha kolay ve basittir int, dökmeye gerek yoktur.

Uzay açısından çok az fark yaratıyor. byteve shortbazı şeyleri karmaşık hale getirecek olursak, bu mikro optimizasyonun buna değdiğini düşünmüyorum çünkü sabit miktarda değişken hakkında konuşuyoruz.

byte, gömülü aygıtlar için programladığınızda veya dosya / ağlarla uğraşırken yararlı ve yararlıdır. Ayrıca bu ilkeller sınırlıdır, ya hesaplamalar gelecekte limitlerini aşabilirse? CalendarSınıf için daha büyük sayılar geliştirebilecek bir uzantı düşünmeye çalışın .

Ayrıca 64-bit işlemciler, halk bu yüzden kullanarak, kayıtlar kaydedilir ve herhangi kaynaklarını kullanmak unutmayın int, shortve diğer ilkel hiç bir fark olmayacaktır. Ayrıca, birçok Java uygulaması değişkenleri * (ve nesneleri) hizalar .


* byte ve shortaynı alanı kaplarint onlar ise yerel değişkenler, sınıf değişkenleri ve hatta örnek değişkenleri. Neden? (Çoğu) bilgisayar sisteminde, değişken adresleri hizalandığından , örneğin tek bir bayt kullanırsanız, aslında iki bayt alırsınız - biri değişkenin kendisi için diğeri dolgu için.

Öte yandan, dizilerde byte1 bayt alır,short 2 bayt ve intdört bayt alır, çünkü dizilerde sadece başlangıç ​​ve belki de sonunun hizalanması gerekir. Bu, örneğin, kullanmak istediğinizde bir fark yaratacaktır System.arraycopy(), o zaman bir performans farkına dikkat edin.


1
Eğlenceli gerçek: Her iki değer için de son değiştiricileri kullanırsanız, işe yarayacaktır. :)
Alexander

7

Çünkü tamsayılar kullanırken aritmetik işlemler daha kısa olanlara göre daha kolaydır. Sabitlerin gerçekten shortdeğerlerle modellenmiş olduğunu varsayın . Ardından API'yı şu şekilde kullanmanız gerekir:

short month = Calendar.JUNE;
month = month + (short) 1; // is july

Açık döküm dikkat edin. Kısa değerler, intaritmetik işlemlerde kullanıldıklarında dolaylı olarak değerlere yükseltilir . (İşlenen yığınında, şortlar ints olarak bile ifade edilir.) Bu kullanımı oldukça zahmetli olacaktır, bu nedenle intdeğerler sabitler için sıklıkla tercih edilir.

Buna kıyasla, depolama verimliliğindeki kazanç minimumdur çünkü yalnızca sabit sayıda sabit bulunur. 40 sabit hakkında konuşuyoruz. Kendi depolama değiştirme intiçin shortkorunmuş olacaktı sen 40 * 16 bit = 80 byte. Daha fazla referans için bu cevaba bakınız .


5

İntegral sabitlerin sığacakları en küçük tipte saklandığı felsefesini kullandıysanız, Java'nın ciddi bir problemi olacaktır: programcılar integral sabitleri kullanarak kod yazdığında, türünün sabitler önemlidir ve öyleyse dokümantasyondaki türe bakın ve / veya gereken tür dönüşümlerini yapın.

Şimdi ciddi bir sorunun ana hatlarını çizdiğimize göre, bu felsefe ile ne gibi faydalar elde etmeyi umabilirsiniz? Bu değişimin çalışma zamanı gözlemlenebilir tek etkisi, yansıma yoluyla sürekli baktığınızda ne tür olacağınız şaşırtıcı olmaz. (ve elbette, sabit türlerini doğru bir şekilde hesaba katmayan tembel / farkında olmayan programcılar tarafından ortaya çıkan hatalar ne olursa olsun)

Artıları ve eksileri tartmak çok kolaydır: bu kötü bir felsefedir.


4

Sanal makinenin tasarım karmaşıklığı, kaç çeşit işlem gerçekleştirebileceğinin bir fonksiyonudur. 32 çarpı tamsayı, 64 bit tamsayı, 32 bit kayan nokta ve 64 bit kayan nokta için birer tane olmak üzere "çarpma" gibi bir komutun dört uygulamasının olması daha kolaydır. Yukarıdakilere göre, daha küçük sayısal tipler için versiyonlar. Daha ilginç bir tasarım sorusu, neden daha az olmaktan ziyade dört tür olması gerektiğidir (64 bit tamsayılarla tüm tamsayı hesaplamaları yapmak ve / veya 64 bit kayan nokta değerleri ile tüm kayan nokta hesaplamaları yapmak). 32 bitlik tamsayıların kullanılmasının nedeni, Java'nın 32 bitlik türlerin 16 bitlik veya 8 bitlik türlerde olduğu kadar hızlı çalışabileceği birçok platformda çalışması bekleniyordu, ancak 64 bitlik türlerdeki işlemlerin fark edilir olduğu Yavaş.sadece 32 bitlik tiplere sahip.

32 bit değerlerde kayan nokta hesaplamaları yapmak için, avantajlar biraz daha az açıktır. Gibi bir hesaplama gibi bazı platformlar vardırfloat a=b+c+d;en hızlı şekilde tüm işlenenleri daha yüksek hassasiyetli bir türe dönüştürüp ekleyerek ve sonucu depolama için 32 bit kayan nokta sayısına dönüştürerek gerçekleştirilebilir. 32 bit kayan nokta değerleri kullanarak tüm hesaplamaları gerçekleştirmenin daha verimli olacağı başka platformlar da vardır. Java'nın yaratıcıları, tüm platformların bir şeyleri aynı şekilde yapması gerektiğine ve 32 bit kayan nokta hesaplamalarının daha hızlı olanlardan daha hızlı olduğu donanım platformlarını tercih etmeleri gerektiğine karar verdiler. ve kayan nokta matematiğinin tipik bir bilgisayarda ve kayan nokta birimi olmayan birçok makinede hassasiyeti. Btw, b, c ve d değerlerine bağlı olarak, yukarıda belirtilenler gibi ifadeleri hesaplarken daha yüksek hassasiyetli ara hesaplamalar kullandığına dikkat edin.float a=b+c+d;bazen tüm ara işlenenlerden elde edilenden önemli ölçüde daha doğru sonuçlar verir float, ancak bazen hassas bir şekilde hesaplanır , ancak bazen biraz daha az doğru olan bir değer verir. Her halükarda Sun, her şeyin aynı şekilde yapılması gerektiğine karar verdi ve minimum hassasiyet floatdeğerlerini kullanmayı seçtiler .

Daha küçük veri türlerinin birincil avantajlarının, çok sayıda veri bir dizide birlikte depolandığında belirgin hale geldiğini unutmayın; 64 bit'ten daha küçük tipteki değişkenlere sahip olmanın hiçbir avantajı olmasa bile, daha küçük değerleri daha kompakt bir şekilde depolayabilen dizilere sahip olmak önemlidir; Yerel değişkeni olmak zorunda bytedeğil bir daha longyedi bayt kaydeder; 1.000.000 sayıdan oluşan bir diziye sahip olmak, her sayıyı bytebirlong7.000.000 bayt dalgalanıyor. Her dizi türünün yalnızca birkaç işlemi desteklemesi gerektiğinden (en önemlisi bir öğeyi okumak, bir öğeyi depolamak, bir dizi içindeki bir dizi öğeyi kopyalamak veya bir dizi öğeyi bir diziden diğerine kopyalamak), dizi türleri, daha fazla doğrudan kullanılabilir ayrık sayısal değere sahip olmanın karmaşıklığı kadar şiddetli değildir.


2

Aslında küçük bir avantaj olurdu. Eğer bir

class MyTimeAndDayOfWeek {
    byte dayOfWeek;
    byte hour;
    byte minute;
    byte second;
}

tipik bir JVM'de, tek bir sınıf içeren bir sınıf kadar alana ihtiyaç duyar int. Bellek tüketimi 8 veya 16 baytlık bir sonraki katına (IIRC, yapılandırılabilir) yuvarlanır, bu nedenle gerçek tasarrufun olduğu durumlar oldukça nadirdir.

Karşılık gelen Calendaryöntemler döndürülürse bu sınıfın kullanımı biraz daha kolay olacaktır a byte. Ancak böyle bir Calendaryöntem yoktur , sadece diğer alanlar nedeniyle get(int)bir döndürmesi gerekir int. Daha küçük tiplerdeki her işlem teşvik eder int, bu nedenle çok fazla döküm gerekir.

Büyük olasılıkla, vazgeçip bir intveya

void setDayOfWeek(int dayOfWeek) {
    this.dayOfWeek = checkedCastToByte(dayOfWeek);
}

O zaman DAY_OF_WEEKne olursa olsun, türü önemli değil.

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.