2011-12-21 6 views
8

ı bir Fraction sınıf var diyelim:Aşağıdaki kod neden java bayt koduyla yeni bir + dup op komutuna çeviriyor?

class Fraction { 
    ... 

    /** Invert current fraction */ 
    public Fraction inverse() { 
     return new Fraction(den,num); 
    } 

    ... 
} 

Ve bu yukarıdaki yöntemin baytkodu olarak çıkıyor şudur: Ben anlamaya çalışıyorum

0 new #1 <xyzTestes/system/fraction/Fraction> 
3 dup 
4 aload_0 
5 getfield #16 <xyzTestes/system/fraction/Fraction.den> 
8 aload_0 
9 getfield #14 <xyzTestes/system/fraction/Fraction.num> 
12 invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>> 
15 areturn 

neden 3 konumundaki yönerge ilk sırada yer aldı. Bunu yapmak için aşağıdakileri yapmamız gerektiğini söyleyebilirim:

new #1 <xyzTestes/system/fraction/Fraction> 
aload_0 
getfield #16 <xyzTestes/system/fraction/Fraction.den> 
aload_0 
getfield #14 <xyzTestes/system/fraction/Fraction.num> 
invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>> 
areturn 

Neden böyle değil?

cevap

10

Kurucu için bayt kodu başladığında, Kesir nesnesi yoktur. new yönergesi yığından Fraction nesnesini (başlatılmamış) ayırır ve yığında bir referans bırakır. dup talimatı, bir referansın, <init>'u ve son olarak areturn için kullanılan ikinciyi kullanmasıdır.

+0

invokespecial, yığındaki Kesir'e bir referans koymayacaktır, o zaman? –

+5

@devoured elysium '() V',' void' fraksiyon' değil döndürür. –

+0

Meh, haklısın. Kısa ve basit açıklama için –

8

Bayt kodunuz yanlış. en içinden çıkalım:

new #1 <xyzTestes/system/fraction/Fraction> 

Stack: Fraction örneği (başlatılmamış belleğe yalnızca bir işaretçi)

aload_0 

Stack: Fraction (hala başlatılmamış), this

getfield #16 <xyzTestes/system/fraction/Fraction.den> 

Yığın: (hala başlatılmamış) Fraction, this.den

aload_0 
getfield #14 <xyzTestes/system/fraction/Fraction.num> 

Stack: Fraction (hala başlatılmamış), this.den, this.num

invokespecial #27 <xyzTestes/system/fraction/Fraction.<init>> 

Stack:

Bu çok önemlidir. Tüm invoke yöntemlerinin tümü, yığının this + tüm bağımsız değişkenlerini içermesini gerektirir. Hem this hem de bağımsız değişkenler yığından alınır. Çağırma işleminden sonra, yalnızca bir dönüş değeri (varsa) yığının üstüne yerleştirilir. <init>, void dönüş türüne sahiptir.

Bu arayacak gelir: Boş yığını üzerinde

areturn 

, JVM dışarı üfleme.