2015-06-25 13 views
220

Soru 1:Java yöntemi iade ifade etmeden derler

neden return ifadesi kalmadan Aşağıdaki kod derleme?

public int a() { 
    while(true); 
} 

Uyarı: ben süre sonra dönüşü eklerseniz o zaman ben bir Unreachable Code Error olsun.

Soru 2: Diğer taraftan

, aşağıdaki kod derleme yapar niye aşağıdaki rağmen

public int a() { 
    while(0 == 0); 
} 

yapmaz.

public int a(int b) { 
    while(b == b); 
} 
+2

2. sorgunun ikinci yarısı sayesinde http://stackoverflow.com/questions/16789832/missing-return-statement-in-a-non-void-method-compiles dosyasının bir kopyası değil. –

cevap

272

Soru 1:

Neden Aşağıdaki kod return ifadesi kalmadan derliyor?

public int a() 
{ 
    while(true); 
} 

Bu

JLS§8.4.7 ile kaplanır: bir yöntem olup, bir dönüş türü için bildirilen

ise (§8.4.5), daha sonra bir derleme zamanı hatası oluşur gövdesi yöntem normal olarak tamamlayabilir (§14.1). Başka bir deyişle, dönüş türüne sahip bir yöntem, yalnızca bir değer döndürme sağlayan bir döndürme ifadesi kullanılarak döndürmelidir; Yöntemin "vücudunun sonunu düşürmesine" izin verilmez. Bir yöntem gövdesindeki iade ifadeleriyle ilgili kesin kurallar için §14.17'ye bakın.

Bir yöntemin dönüş türüne sahip olması ve geri dönüş ifadeleri içermemesi mümkündür. İşte bir örnek: derleyici döngü (true elbette, her zaman doğrudur) sonlandırmak asla bilir, bu "normal dönüş" olamaz işlevini bildiğinden

class DizzyDean { 
    int pitch() { throw new RuntimeException("90 mph?!"); } 
} 

(sonunu düşüyorlar onun Gövde) ve dolayısıyla return diye bir şey yok.

Soru 2: neden,

public int a() { while(0 == 0); } 

Aşağıdaki kod derleme aşağıdaki olsa bile Öte yandan

bunu dikkate almaz. 0 == 0 durumda

public int a(int b) 
{ 
    while(b == b); 
} 

, derleyici döngü (yani 0 == 0 her zaman doğru olacaktır) sona asla bilir. Ancak ,'u b == b için bilmiyor.

Neden değil?

Derleyici, constant expressions (§15.28) öğelerini anlıyor. §15.2 - Forms of Expressions(garip bir şekilde bu cümle §15.28 olmadığından) alıntı:

Bazı ifadeler var derleme sırasında tespit edilebilir bir değer. Bunlar sabit ifadeleri (§15.28). katılan bir değişken olduğundan sizin b == b örnekte

, bu sabit bir ifade değildir ve derleme zamanında belirlenecek belirtilmemiştir. Biz her zaman (not == itself olduğunu b QBrute pointed out gibi bir double, olsaydı, biz kolayca Double.NaN aptal edilebilir ancak,) bu durumda gerçek olacak görebilirsiniz, ancak JLS sadece sabit ifadeler belirlenir belirtir derleme zamanında, derleyicinin sabit olmayan ifadeleri değerlendirmeye çalışmasına izin vermez. neden olmasın bayou.io raised a good point: Eğer derleme zamanında değişkenleri içeren ifadeleri belirlemek için yola çıkmaya başlarsanız, nerede durursunuz? b == b (NaN değerleri için olmayan) açık, ama ne hakkında a + b == b + a? Veya (a + b) * 2 == a * 2 + b * 2? Çizgiyi sabit olarak çizmek anlamlıdır.

Bu ifadeyi ifade etmediğinden, derleyici döngünün hiçbir zaman sona ermeyeceğini bilemez, bu nedenle yöntemin normal olarak   — dönmesine izin verilmediğini düşünür. return kullanın. Yani return eksikliğinden şikayet ediyor.

32

Değil belirtilen türde bir değer döndürmek için bir söz gibi yazması bir yöntem dönüşü düşünmek ilginç olabilir, ama bir söz değil olarak belirtilen türde değil bir değer döndürmek için. Bir şey asla geri Dolayısıyla, eğer sen sözünü kırma ve böylece herhangi değildir aşağıdaki yasal şunlardır:

  1. sonsuza Döngü:

    X foo() { 
        for (;;); 
    } 
    
  2. sonsuza recursing:

    X foo() { 
        return foo(); 
    } 
    
  3. Bir özel durumun atılması

(Yineleme düşünülecek bir eğlenceli buluyorum: Derleyici, yöntemin X türünde bir değer döndüreceğine inanır (ancak her neyse), ancak bu doğru değildir, çünkü hiçbir kod yoktur. X'u oluşturma veya sağlama hakkında herhangi bir fikriniz var.)

8

Bayt koduna bakıldığında, döndürülenler tanımla eşleşmiyorsa bir derleme hatası alırsınız.

Örnek:

for(;;) gösterecektir baytkodlarına: böylece

L0 
    LINENUMBER 6 L0 
    FRAME SAME 
    GOTO L0 

Not Bu şimdiye kadar bir dönüş isabet etmez herhangi dönüş bayt

eksikliği ve yapmayan yanlış tür döndür. Karşılaştırma için

, bir yöntem gibi:

public java.lang.String getBar(); 
    Code: 
     0: aload_0 
     1: getfield  #2; //Field bar:Ljava/lang/String; 
     4: areturn 

Not Şimdi biz eğer

"başvuru döndürmek" anlamına gelen "areturn":

public String getBar() { 
    return bar; 
} 

aşağıdaki baytkodlarına döndürür aşağıdakileri yapın:

public String getBar() { 
    return 1; 
} 

aşağıdaki koddan döndürür:

public String getBar(); 
    Code: 
    0: iconst_1 
    1: ireturn 

Şimdi tanımında tip dönüş int anlamına ireturn dönüş türünü, uyuşmadığını görebilirsiniz.

Gerçekten de aşağıya inen şey, yöntemin bir dönüş yoluna sahip olması durumunda, bu yolun dönüş türüyle eşleşmesidir. Ancak, hiçbir geri dönüş yolunun üretilmediği bayt kodunda örnekler vardır ve bu nedenle kuralın kırılması söz konusu değildir.

İlgili konular