Java API neden kullanılır? int
ne zaman, short
hatta byte
yeterli olabilir?
Örnek: The DAY_OF_WEEK
Sınıftaki alan Calendar
kullanır int
.
Fark çok az ise, o zaman neden (bu veri türlerini yapmak short
,int
) var?
Java API neden kullanılır? int
ne zaman, short
hatta byte
yeterli olabilir?
Örnek: The DAY_OF_WEEK
Sınıftaki alan Calendar
kullanır int
.
Fark çok az ise, o zaman neden (bu veri türlerini yapmak short
,int
) var?
Yanıtlar:
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 int
ve tip long
ve olmayan küçük türleri için.
(Bir taraf: Daha küçük türler ( byte
ve 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 long
değ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_WEEK
olarak 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 double
ve long
iki yuva kaplar). Bu yüzden bir alanı açıkça belirtmek short
veya byte
herhangi bir belleği kaydetmemek.
int
. Başka bir uygulamaya referansınız varsa, yanıtı güncelleyip bağlantıyı buna göre eklerdim.
(Neredeyse) tüm işlemler byte
, short
onları 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. byte
ve short
bazı ş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? Calendar
Sı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
, short
ve diğer ilkel hiç bir fark olmayacaktır. Ayrıca, birçok Java uygulaması değişkenleri * (ve nesneleri) hizalar .
* byte
ve short
aynı 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 byte
1 bayt alır,short
2 bayt ve int
dö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.
Çünkü tamsayılar kullanırken aritmetik işlemler daha kısa olanlara göre daha kolaydır. Sabitlerin gerçekten short
değ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, int
aritmetik 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 int
değ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 int
için short
korunmuş olacaktı sen 40 * 16 bit = 80 byte
. Daha fazla referans için bu cevaba bakınız .
İ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.
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 float
değ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 byte
değil bir daha long
yedi bayt kaydeder; 1.000.000 sayıdan oluşan bir diziye sahip olmak, her sayıyı byte
birlong
7.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.
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 Calendar
yöntemler döndürülürse bu sınıfın kullanımı biraz daha kolay olacaktır a byte
. Ancak böyle bir Calendar
yö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 int
veya
void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
O zaman DAY_OF_WEEK
ne olursa olsun, türü önemli değil.