Soru Neden Java'nın + =, - =, * =, / = bileşik atama operatörleri döküm gerektirmiyor?


Bugüne kadar, örneğin şunu düşündüm:

i += j;

sadece bir kısayol:

i = i + j;

Ama ya şunu deneyelim:

int i = 5;
long j = 8;

Sonra i = i + j; derleme değil ama i += j; iyi derler.

Bu aslında demek i += j; böyle bir şey için bir kısayol i = (type of i) (i + j)?


3286
2018-01-03 10:10


Menşei


Java'nın buna izin vermesine şaşırıyorum, öncekinden daha katı bir dil. Casting'teki hatalar kritik arızaya yol açabilir, Ariane5 Flight 501'de olduğu gibi, 16 bitlik bir tamsayıya 64 bitlik bir floatın çarpmasıyla sonuçlandı. - SQLDiver
Java'da yazılan bir uçuş kontrol sisteminde, bu sizin endişelerinizden en azı olacaktır. - Ross Drew
Olası kopya Javada + = 10 ve a = a + 10 arasındaki fark? - phuclv
Aslında i+=(long)j; hatta iyi derler. - Tharindu
Bence Douglas Crockford her şeyden sonra tartışmayı kazanır ... Bu davranış korkunçtur ve birçok dil dönüşümler etrafında benzer problemlere sahiptir. - Aluan Haddad


Cevaplar:


Her zaman olduğu gibi, bu sorulara cevap olarak, JLS cevabı tutar. Bu durumda §15.26.2 Bileşik Atama Operatörleri. Bir özü:

Formun bileşik atama ifadesi E1 op= E2 eşdeğerdir E1 = (T)((E1) op (E2)), nerede T türü E1, bunun haricinde E1 sadece bir kez değerlendirilir.

Bir örnek §15.26.2

[...] aşağıdaki kod doğrudur:

short x = 3;
x += 4.6;

ve x değeri 7'ye eşittir, çünkü aşağıdakilere eşdeğerdir:

short x = 3;
x = (short)(x + 4.6);

Diğer bir deyişle, varsayımınız doğrudur.


2212
2018-01-03 10:15



Yani i+=j kendimi kontrol ettiğimde derleme yapar, ancak bu doğru bir şekilde kesilir mi? Eğer durum buysa, neden i = i + j'de olmasına izin vermiyor? Neden bizi orada böldün? - bad_keypoints
@ronnieaka: Dil tasarımcılarının bir durumda bunu hissettiğini tahmin ediyorum (i += j), diğer durumun aksine hassasiyet kaybının arzu edildiğini varsaymak daha güvenlidir (i = i + j) - Lukas Eder
Hayır, onun tam orda, benim önümde! Üzgünüm, daha önce fark etmedim. Cevabın gibi E1 op= E2 is equivalent to E1 = (T)((E1) op (E2))Yani, bu tür bir tür aşağıdan aşağıya doğru yazım (aşağıdan uzunya doğru). Oysa i = i + j'de, bunu açıkça yapmak zorundayız, yani (T) parçası E1 = ((E1) op (E2)) Öyle değil mi? - bad_keypoints
Bunun, açık bir oyuncudan ve / veya f bir çift edebi bir kısaca eklemek durumunda postfix? - Andrey Akhmetov
Java derleyicisinin neden bir yazım eklemesinin olası bir nedeni, uyumsuz türlerde aritmetik yapmaya çalışıyorsanız, sözleşmeli formu kullanarak sonucun bir yazımını gerçekleştirmenin bir yolu yoktur. Sonuçtaki bir tahmin, genellikle problemli argümanın bir yazımından daha doğrudur. Uyumsuz türler kullanıldığında kastın kullanılmasını gereksiz kılabilir, çünkü her zaman derleyicinin hata yapmasına neden olur. - ThePyroEagle


Bu dökümün iyi bir örneği * = veya / = kullanıyor

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

veya

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

veya

char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'

veya

char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'

442
2018-01-03 10:20



@SajalDutta Bu referansı almadım. Akıl açıklıyor mu? - Akshat Agarwal
@AkshatAgarwal ch bir char. 65 * 1.5 = 97.5 -> Anladın mı? - Sajal Dutta
Evet, ama buraya yeni gelenlerin geldiğini görebiliyorum, bunu okuyarak, ve herhangi bir karakteri büyük harften küçük harfe dönüştürerek 1,5 ile çarparak düşünerek ayrılabiliyorum. - Dawood ibn Kareem
@DavidWallace Herhangi bir karakter olduğu sürece A ;) - Peter Lawrey
@PeterLawrey & @DavidWallace Senin ortaya çıkaracağım gizli- ch += 32= D - Minhas Kamal


Çok güzel bir soru. Java Dil özellikleri önerinizi doğrular.

Örneğin, aşağıdaki kod doğrudur:

short x = 3;
x += 4.6;

ve x değeri 7'ye eşittir, çünkü aşağıdakilere eşdeğerdir:

short x = 3;
x = (short)(x + 4.6);

223
2018-01-03 10:17



Veya daha eğlenceli: "int x = 33333333; x + = 1.0f;". - supercat


Evet,

temelde yazdığımız zaman

i += l; 

derleyici bunu

i = (int)(i + l);

Sadece kontrol ettim .class dosya kodu

Gerçekten bilmek için iyi bir şey


163
2018-01-03 10:19



Bunun hangi classfile olduğunu söyleyebilir misin? - Andrey Akhmetov
@hexafraction: sınıf dosyası ile ne demek istiyorsun? yazımda bahsettiğim sınıf dosyasını sorarsanız, java sınıfınızın zorunlu sürümünden daha - Umesh Awasthi
Oh, belirli bir sınıf dosyasına dahil olduğuna inanmamı sağlayan "sınıf" dosya kodundan bahsettin. Şimdi ne demek istediğini anlıyorum. - Andrey Akhmetov
Tüm harflerden, aslında "l" yi seçtiniz (küçük harf L) ... - Bogdan Alexandru
@glglgl Bu vakaları ayırt etmek için yazı tipine güvenmesi gerektiğine katılmıyorum ... ama herkesin en iyi olduğunu düşündüğü şeyi seçme özgürlüğü var. - Bogdan Alexandru


den dökmek gerekir long için int  explicitly durumunda i = i + l  daha sonra doğru çıktıyı derler ve verir. sevmek

i = i + (int)l;

veya

i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

ama durumunda += Sadece iyi çalışıyor çünkü operatör açıkça sağ değişkenin türünden soldaki değişkenin türüne tür dökümünü açıkça yapıyor, bu yüzden açıkça yayınlanmasına gerek yok.


85
2018-01-03 10:15



Bu durumda, "kapalı cast" kayıp olabilir. Gerçekte, LukasEder cevabında belirttiği gibi, int gerçekleştirilir sonra  +. Derleyici (gerçekten? long için int. - Romain


Sorun burada tip dökümü içerir.

İnt ve long eklediğinizde,

  1. İnt nesnesi uzun süre dökülür ve her ikisi de eklenir ve uzun bir nesne alırsınız.
  2. ancak uzun nesne, dolaylı olarak int için kullanılamaz. Yani, bunu açıkça yapmanız gerekiyor.

Fakat += yazıya dökecek şekilde kodlanmıştır. i=(int)(i+m)


56
2018-01-03 10:20





Java tipi dönüşümler, atama işleminin sağ tarafındaki ifadenin türü, atamanın sol tarafındaki değişken türüne güvenli bir şekilde yükseltilebildiğinde otomatik olarak gerçekleştirilir. Böylece güvenli bir şekilde atayabiliriz:

 byte -> kısa -> int -> uzun -> yüzer -> çift. 

Aynı şey başka bir şekilde işe yaramayacaktır. Örneğin, otomatik olarak bir uzunluğa bir int dönüşümü yapamayız çünkü birincisi ikincisinden daha fazla depolama gerektirir ve sonuçta bilgi kaybolabilir. Böyle bir dönüşümü zorlamak için açık bir dönüşüm gerçekleştirmeliyiz.
Türü - Dönüşüm


47
2018-01-23 05:50



Hey ama long 2 kat daha büyüktür float. - Sarge Borsch
bir float her şeyi tutamaz int değer ve double her şeyi tutamaz long değer. - Alex MDC
"Güvenli bir şekilde dönüştürülmüş" ile ne demek istiyorsun? Cevabın ikinci kısmından, float -> long durumunda doğru olmayan otomatik dönüşümü (örtülü cast) kastettiğinizi söyleyebilirim. yüzer pi = 3.14f; uzun b = pi; derleyici hatasıyla sonuçlanır. - Luke
Kayan nokta ilkel türlerini tamsayı ilkel türleri ile ayırmaktan daha iyi olursunuz. Aynı şey değiller. - ThePyroEagle
Java, kalıp içermeyen davranışların beklentilerle eşleşeceği, ancak genellikle hatalı olan kalıplarda döküm gerektirmeyen birçok desende kalıpların kullanılmasını gerektiren basit dönüştürme kurallarına sahiptir. Örneğin, bir derleyici kabul eder double d=33333333+1.0f; Şikayette bulunmaksızın, sonuç 33333332.0 muhtemelen ne amaçla yapılmış olsa da (tesadüfen, 33333334.0f'nin aritmetik olarak doğru cevabı float veya int). - supercat


Bazen böyle bir soru bir röportajda istenebilir.

Örneğin, yazdığınızda:

int a = 2;
long b = 3;
a = a + b;

otomatik yazım yok. C ++ 'da yukarıdaki kodu derlerken herhangi bir hata olmayacaktır, ancak Java’da Incompatible type exception.

Bundan kaçınmak için kodunuzu şöyle yazmalısınız:

int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting

37
2017-12-02 10:40



Karşılaştırma ile ilgili içgörü için teşekkürler op C ++ 'da Java' da kullanımı için kullanın. Her zaman bu türden trivia'ları görmeyi severim ve sanırım çoğu zaman dışarıda bırakılabilecek olan konuşmaya bir şeyler katıyorlar. - Thomas
Ancak sorunun kendisi olduğu ilginç, bunu soruyorum bir röportajda aptalca Kişinin kaliteli bir kod üretebileceğini kanıtlamaz - sadece bir Oracle sertifika sınavına hazırlanmak için yeterli sabrı olduğunu kanıtlar. Tehlikeli bir otomatik dönüşüm kullanarak uyumsuz türleri "önlemek" ve böylece olası taşma hatasını gizlemek kanıtlıyor Kişinin iyi bir kalite kodu üretmesi mümkün değildir. Tüm bu otomatik dönüşümler, otomatik kutulama ve hepsi için Java yazarlarına lanet olsun! - Honza Zidek


Ana fark şu ki a = a + b, herhangi bir yazım hatası olmaz ve bu yüzden derleyici, siz yazım için değil, size kızar. Fakat a += b, gerçekten ne yapıyor typecasting b ile uyumlu bir türe a. Eğer yaparsan

int a=5;
long b=10;
a+=b;
System.out.println(a);

Gerçekten ne yapıyorsun:

int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);

18
2018-06-07 23:27



Bileşik atama operatörleri, sağ işlenen değil, ikili işlemin sonucunun daraltılması işlemini gerçekleştirir. Örneğinizde, 'a + = b', 'a = a + (int) b' değerine eşdeğer değildir, ancak burada diğer yanıtlarla açıklandığı gibi, 'a = (int) (a + b)' ye eşdeğerdir. - Lew Bloch


Burada ince nokta ...

İçin örtük bir tahmin var i+j ne zaman j bir çift ve i int Java HER ZAMAN aralarında bir işlem olduğunda bir tam sayıyı ikiye dönüştürür.

Netleşmeştirmek i+=j nerede i bir tam sayı ve j bir çift olarak tanımlanabilir

i = <int>(<double>i + j)

Görmek: örtük dökümün bu açıklaması

Tahmin etmek isteyebilirsiniz j için (int) bu durumda açıklık için.


7
2018-01-18 20:07