Aşırı yük yöntemine bayt argümanları iletme


12

Bu kod snippet'i bazı sınavlardan aldım, IDE'yi kullanarak yürüttüm ve uzun, uzun bir sonuç aldım ama doğru cevap Byte, Byte , neden farklı sonuç aldım? Soru JDK 11 ile ilgili

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

REDAKTE:

Kod buraya alındı: Oracle Sertifikasyonuna Genel Bakış ve Örnek Sorular (Sayfa: 13, Soru: 5)


1
Byte b = 5;Başkent B ile olmadığından emin misin?
Joop Eggen

4
long, longJava8 de çok FYI olsun ... Neden dürüst olmak emin değilim, bir cevap bekliyorum :)
sp00m

Yanıtlar:


6

Bu nedenle, derleme zamanında yöntem imzasını belirlemek için Java dil belirtiminden geçerseniz, açık olacaktır:

  1. İlk aşama (§15.12.2.2), boks veya kutudan çıkarma dönüşümüne veya değişken arity yöntemi çağırma kullanımına izin vermeden aşırı yük çözünürlüğü gerçekleştirir. Bu aşamada uygulanabilir bir yöntem bulunamazsa işlem ikinci aşamaya devam eder.

  2. İkinci aşama (§15.12.2.3), boks ve kutudan çıkarmaya izin verirken aşırı yük çözünürlüğü gerçekleştirir, ancak yine de değişken arity yöntemi çağırma kullanımını engeller. Bu aşamada uygulanabilir bir yöntem bulunamazsa işlem üçüncü aşamaya devam eder.

  3. Üçüncü aşama (§15.12.2.4) aşırı yüklemenin değişken arity yöntemleri, boks ve kutudan çıkarılması ile birleştirilmesine izin verir.

Dolayısıyla, yukarıdaki adımlardan, ilk aşamada Java derleyicisinin bunu yapan bir eşleştirme yöntemi bulacağı açıktır doCalc(long a,long b). Yöntemin doCalc(Byte s1, Byte s2), görüşme sırasında otomatik kutulamaya ihtiyacı vardır, böylece daha az tercih edilir.


1
Neden longkabul ettiğine ilişkin olarakbyte , genişleyen ilkel bir dönüşüm izliyor gibi görünüyor : docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2 . Temel olarak, +widening -boxing -varargso +widening +boxing -varargszaman +widening +boxing +varargs.
sp00m

@kbo Neden doğru cevabın olduğunu düşünüyorsunuz Byte, Byte?
Amit Bera

3
@kbo Sanırım doğru cevap yanlış :) Mümkünse yazarları bu soruya işaret etmeye değer olabilir.
sp00m

3
@ sp00m Bu soruyu Oracle'ın örneklerinde buldum, lütfen düzenlenen bölüme bir göz atın
kbo

@kbo Wow ... O zaman nasıl ilerleyeceğine dair bir fikrim yok!
sp00m

2

Lütfen okuyun dönüşümler hakkındaki JLS bölümünü .

Sizin durumunuzda olan şey, çalışma zamanı sırasında JVM'nin genişleyen bir dönüşüm gerçekleştirmeyi seçmesidir byte -> long çünkü bu dönüşüm daha güvenlidir, çünkü bunun neden olmadığı garanti edilir.RuntimeException .

Dönüştürme byteiçin Bytede denir boks neden olabilir OutOfMemoryError JVM yığın üzerine de nesne olduğu gibi:

Sarıcı sınıflarından birinin yeni bir örneğinin (Boolean, Byte, Character, Short, Integer, Long, Float veya Double) tahsis edilmesi ve yetersiz depolama alanı bulunması durumunda, bir boks dönüşümü OutOfMemoryError ile sonuçlanabilir.

Bu nedenle, daha güvenli byte -> long genişletme dönüşümü tercih edilir.


2
Sadece nota, boks byteiçin Byteasla neden OutOfMemoryExceptiontüm değerleri beri, Byteiçten önbelleğe - (127 -128). Ancak, diğer türlerle aynı olmayabilir, bu nedenle başparmak kuralı olarak, genişletme dönüşümü öncelik kazanır.
Pavel Smirnov

1

Doğru aşırı yükü bulmak için sipariş:

  1. parametre sayısına göre
  2. boks / kutudan çıkarma
  3. varyasyon parametreleri

Yani

  • Sonuç bnerede olursaByteByte, Byte .
  • Eğer geçmiş olsaydı new byte[] { b, b }sonuç olurdubyte, byte .
  • İki bayt b'den geçilirse , bayttan int'e genişleme mümkündür ve sonuçlong, long .
  • Uzun, uzun aşırı yük kaldırıldığında, Byte, Bytesonuç ortaya çıkar.
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.